c#winform窗体如何实现服务器实时接收数据,不借助button

c#winform窗体如何实现服务器实时接收数据,不借助button,第1张

宽泛的讲,有两种方式,实现Client和Server的实时通讯(数据接收)。

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

}


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/174036.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-26
下一篇2023-03-26

发表评论

登录后才能评论

评论列表(0条)

    保存