1、 Pull 也就是拉。 即Client把数据从Server中拉出来。
因为winform本质是事件驱动,如果不想用button,那么最简单的方式就是用定时器(timer), 比如每10秒请求一次数据,
这种方式本质上和button没有区别,还是通过事件来驱动应用,只不过是“自动”的去读取数据。
优点是简单, 缺点是不及时(如果数据是1秒一变,这个10秒的间隔就太长了),而且资源利用率较低(如果1小时都没有变化, 这10秒一次的刷新就很占用资源)
2、Push 推,即Server将信息推送到Client中去。
Winform中实现推送信息,一般需要和Server建立连接,连接后,当Server需要推送(比如数据有更新)时,才向Client中发送信息。
优点是数据的时效性较好,而且资源利用合理。
缺点是需要大量的代码(相比定时器那种方法)
Push模式可以参考“观察者模式”的开发方式。
从服务器获取数据可以用两种方式,使用HTTP协议访问服务器预留的接口,接收服务器返回的数据,这种方法使用WEB服务器。另一种是建立socket连接,与服务器通信。通信过程中要遵守传输协议,HTTP方式要遵守HTTP协议,socket形式底层遵守TCP/IP协议,应用层可以自己定义通讯协议。有一些成熟的协议。SOAP,XMPP等使用XML方式传输数据。
C++通过socket编程实现服务端与客户端的通讯,代码如下(个人环境下测试正常,如果遇到运行send发送报错,请检查服务器端口是否被占用,调试的时候请先运行服务端程序在运行客服端,一定要加载库函数ws2_32.lib,发送字符时应该多加一个空字符作为结束字符):服务器端程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Server.cpp : Defines the entry point for the console application.
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std
int main(int argc, char* argv[])
{
const int BUF_SIZE = 64
WSADATAwsd //WSADATA变量
SOCKETsServer //服务器套接字
SOCKETsClient //客户端套接字
SOCKADDR_INaddrServ //服务器地址
charbuf[BUF_SIZE] //接收数据缓冲区
charsendBuf[BUF_SIZE]//返回给客户端得数据
intretVal //返回值
//初始化套结字动态库
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
cout <<"WSAStartup failed!" <<endl
return 1
}
//创建套接字
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
if(INVALID_SOCKET == sServer)
{
cout <<"socket failed!" <<endl
WSACleanup()//释放套接字资源
return -1
}
//服务器套接字地址
addrServ.sin_family = AF_INET
addrServ.sin_port = htons(4999)
addrServ.sin_addr.s_addr = INADDR_ANY
//绑定套接字
retVal = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN))
if(SOCKET_ERROR == retVal)
{
cout <<"bind failed!" <<endl
closesocket(sServer) //关闭套接字
WSACleanup() //释放套接字资源
return -1
}
//开始监听
retVal = listen(sServer, 1)
if(SOCKET_ERROR == retVal)
{
cout <<"listen failed!" <<endl
closesocket(sServer) //关闭套接字
WSACleanup() //释放套接字资源
return -1
}
//接受客户端请求
sockaddr_in addrClient
int addrClientlen = sizeof(addrClient)
sClient = accept(sServer,(sockaddr FAR*)&addrClient, &addrClientlen)
if(INVALID_SOCKET == sClient)
{
cout <<"accept failed!" <<endl
closesocket(sServer) //关闭套接字
WSACleanup() //释放套接字资源
return -1
}
while(true)
{
//接收客户端数据
ZeroMemory(buf, BUF_SIZE)
retVal = recv(sClient, buf, BUF_SIZE, 0)
if (SOCKET_ERROR == retVal)
{
cout <<"recv failed!" <<endl
closesocket(sServer) //关闭套接字
closesocket(sClient) //关闭套接字
WSACleanup() //释放套接字资源
return -1
}
if(buf[0] == '0')
break
cout <<"客户端发送的数据: " <<buf <<endl
cout <<"向客户端发送数据: "
cin >>sendBuf
send(sClient, sendBuf, strlen(sendBuf), 0)
}
//退出
closesocket(sServer) //关闭套接字
closesocket(sClient) //关闭套接字
WSACleanup() //释放套接字资源
return 0
}
客户端程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "winsock2.h"
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std
BOOL RecvLine(SOCKET s, char* buf)//读取一行数据
int main(int argc, char* argv[])
{
const int BUF_SIZE = 64
WSADATA wsd//WSADATA变量
SOCKET sHost//服务器套接字
SOCKADDR_IN servAddr//服务器地址
char buf[BUF_SIZE]//接收数据缓冲区
char bufRecv[BUF_SIZE]
int retVal//返回值
//初始化套结字动态库
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
cout <<"WSAStartup failed!" <<endl
return -1
}
//创建套接字
sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
if(INVALID_SOCKET == sHost)
{
cout <<"socket failed!" <<endl
WSACleanup()//释放套接字资源
return -1
}
//设置服务器地址和端口
servAddr.sin_family =AF_INET
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1")
servAddr.sin_port = htons((short)4999)
int nServAddlen = sizeof(servAddr)
//连接服务器
retVal=connect(sHost,(LPSOCKADDR)&servAddr, sizeof(servAddr))
if(SOCKET_ERROR == retVal)
{
cout <<"connect failed!" <<endl
closesocket(sHost)//关闭套接字
WSACleanup()//释放套接字资源
return -1
}
while(true)
{
//向服务器发送数据
ZeroMemory(buf, BUF_SIZE)
cout <<" 向服务器发送数据: "
cin >>buf
retVal = send(sHost, buf, strlen(buf), 0)
if (SOCKET_ERROR == retVal)
{
cout <<"send failed!" <<endl
closesocket(sHost)//关闭套接字
WSACleanup()//释放套接字资源
return -1
}
//RecvLine(sHost, bufRecv)
ZeroMemory(bufRecv, BUF_SIZE)
recv(sHost, bufRecv,BUF_SIZE , 0)// 接收服务器端的数据, 只接收5个字符
cout <<endl <<"从服务器接收数据:"<<bufRecv
cout<<"\n"
}
//退出
closesocket(sHost)//关闭套接字
WSACleanup()//释放套接字资源
return 0
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)