由于代码的注释已经很详尽了,所以这里不再作过多说明.仅仅贴出代码和结果图.
值得注意的是必须先启动server程序再启动client.
Server:
1 #include <WINSOCK2.H> //套接字库
2 #include <stdio.h>
3
4 #define PORT 6000 //服务器端口
5 #define MSGSIZE 1024 //收发缓冲区的大小
6
7 #pragma comment(lib, "ws2_32.lib") //链接静态库
8
9 DWORD WINAPI FunThread(LPVOID); //创建一个线程,专门用来接收数据
10
11 SOCKET sClient; //连接所用套节字
12 SOCKET sListen; //监听套接字
13 SOCKADDR_IN client; //保存客户的地址信息
14 int iaddrSize = sizeof(SOCKADDR_IN);
15
16 int main()
17 {
18
19 WSADATA wsaData; //WSADATA结构体中主要包含了系统所支持的Winsock版本信息
20 SOCKADDR_IN local; //定义本地套接字地址
21 char s_Message[MSGSIZE]; //收发缓冲区
22
23 WSAStartup(0x0202, &wsaData); //初始化套接字库
24
25 sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建服务器监听套节字。TCP协议
26
27 local.sin_family = AF_INET; //AF_INET指明使用TCP/IP协议族
28 local.sin_port = htons(PORT);//指明连接服务器的端口号
29 local.sin_addr.s_addr = htonl(INADDR_ANY);//自动获取本机地址
30
31 bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));//地址绑定到套接字
32
33 listen(sListen, 1);//开始监听
34
35 sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);//建立连接,返回用于连接的套接字
36 printf("Accepte client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));//输出客户端的IP地址和端口
37
38
39 HANDLE hThread=CreateThread(NULL,0,FunThread,0,0,0);//运行至此创建专门的接收线程用于接收客户端发送
40 //的数据,在监听主线程上创建一个新的数据接收线程
41 CloseHandle(hThread);//关闭线程句柄
42
43
44 //用于从服务器端向客户端发送数据
45 while (TRUE)
46 {
47 printf("Server Send:");
48 //从键盘输入
49 gets(s_Message);
50 //发送数据
51 send(sClient, s_Message, strlen(s_Message), 0);
52 }
53 return 0;
54 }
55
56
57 //当接收数据时调用此线程函数
58 DWORD WINAPI FunThread(LPVOID)
59 {
60 char c_Message[MSGSIZE]; //接收数据缓冲区
61 int ret; //接收字节的个数
62 while (TRUE)
63 {
64 ret = recv(sClient, c_Message, MSGSIZE, 0);//接收数据到缓冲区
65
66 //判断是否成功接收,如果未成功接收则重启监听,将原缓冲区的数据归零
67 if(ret==SOCKET_ERROR)
68 {
69 printf("\nclient is closed!");
70
71 sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);//重新开始监听
72 printf("\nAccepte new client:%s:%d", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
73 memset(c_Message,0,1024);//将原来的client message归零
74 continue;
75 }
76 c_Message[ret] = '\0';
77 printf("\nReceived: %s\n", c_Message);
78 }
79 return 0;
80 }<strong>
81 </strong>
Client:
1 #include <WINSOCK2.H> //套接字库
2 #include <stdio.h>
3
4 #define SERVER_ADDRESS "127.0.0.1" //服务器端IP地址,由于服务也在本地机器上所以用环回地址127.0.0.1
5
6 #define PORT 6000 //客户端绑定端口
7 #define MSGSIZE 1024 //客户端接收数据缓冲区大小
8 #pragma comment(lib, "ws2_32.lib")
9
10 DWORD WINAPI FunThread(LPVOID); //对于客户端接收数据的线程函数
11
12 SOCKET sClient; //客户端套接字
13 SOCKADDR_IN server; //服务器端套接字
14
15
16 int main()
17 {
18 WSADATA wsaData;
19 char c_Message[MSGSIZE]; //数据缓冲区
20
21 WSAStartup(0x0202, &wsaData); //初始化套接字库
22
23 sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建客户端套接字
24
25 memset(&server, 0, sizeof(SOCKADDR_IN)); //先将保存地址的server置为全0
26 server.sin_family = PF_INET; //声明地址格式是TCP/IP地址格式
27 server.sin_port = htons(PORT); //指明连接服务器的端口号
28 server.sin_addr.s_addr = inet_addr(SERVER_ADDRESS); //指明连接服务器的IP地址
29
30
31 connect(sClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN)); //连到刚才指明的服务器上
32
33 HANDLE hThread=CreateThread(NULL,0,FunThread,0,0,0);;//客户端开辟接收数据线程
34 CloseHandle(hThread);
35
36 //客户端向服务器发送数据
37 while (TRUE)
38 {
39 printf("Client Send:");
40 gets(c_Message);
41
42 send(sClient, c_Message, strlen(c_Message), 0);
43 if(!strcmp(c_Message,"exit"))//client自身退出
44 exit(1);
45 }
46
47 // 释放连接和进行结束工作
48 closesocket(sClient);
49 WSACleanup();
50 return 0;
51 }
52
53 //接收线程函数
54 DWORD WINAPI FunThread(LPVOID)
55 {
56 char s_Message[MSGSIZE];//定义接收缓冲区
57 int ret;
58 while (TRUE)
59 {
60 ret = recv(sClient, s_Message, MSGSIZE, 0);//接收服务器端的数据
61
62
63 //判断是否接收
64 if(ret==SOCKET_ERROR)
65 {
66 printf("\nServer is closed!\n");
67 exit(1);
68 }
69 s_Message[ret] = '\0';
70 //显示接收数据
71 printf("\nReceived: %s\n", s_Message);
72
73 //如果服务器端发送exit则client退出
74 if(!strcmp(s_Message,"exit"))//server让client退出
75 exit(1);
76 }
77 return 0;
78 }<strong>
79 </strong>
运行结果如下: