由于代码的注释已经很详尽了,所以这里不再作过多说明.仅仅贴出代码和结果图.


值得注意的是必须先启动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>



 


运行结果如下:

Java套接字关闭的原因 套接字实现_Java套接字关闭的原因


Java套接字关闭的原因 套接字实现_套接字_02