本次实验利用TCP/IP, 语言环境为 C/C++
利用套接字Socket编程,以及线程处理,
实现Server/CLient 之间多人的聊天系统的基本功能。
结果大致如:
下面贴上代码(参考参考...)
Server 部分:
1 /* TCPdtd.cpp - main, TCPdaytimed */
2
3 #include
4 #include
5 #include
6 #include
7 #include "conio.h"
8 #include
9 #include
10 #include
11
12 #define QLEN 5
13 #define WSVERS MAKEWORD(2, 0)
14 #define BUFLEN 2000 // 缓冲区大小
15 #pragma comment(lib,"ws2_32.lib") //winsock 2.2 library
16
17 SOCKET msock, ssock; /* master & slave sockets */
18 SOCKET sockets[100] = {NULL};
19
20 int cc;
21 char *pts; /* pointer to time string */
22 time_t now; /* current time */
23 char buf[2000]; /* buffer */
24 char *input;
25 HANDLE hThread1,hThread[100] = {NULL};
26 unsigned int threadID,ThreadID[100],number;
27
28 struct sockaddr_in fsin;
29 struct sockaddr_in Sin;
30
31 unsigned int __stdcall Chat(PVOID PM)
32 {
33 char buf1[2000];
34 char buf2[2000];
35 char buf3[2000];
36 char buf4[2000];
37 (void) time(&now);
38 pts = ctime(&now);
39 sockets[number] = ssock;
40 SOCKET sock = ssock;
41 ThreadID[number] = threadID;
42 unsigned int threadid = threadID;
43 sprintf(buf1," 时间: %s \t【我的线程号: %d 】\n",pts,threadid);
44 (void) send(sock,buf1, sizeof(buf1), 0);
45 sprintf(buf2," 线程号 <%d> 客户
46 printf("%s ",buf2);
47 printf("\t将自动把此数据发送给所有客户&#xff01; \n");
48 for(int i&#61;0;i<&#61;number;i&#43;&#43;)
49 {
50 if(sockets[i] !&#61; NULL && sockets[i] !&#61; sock)
51 {
52 (void) send(sockets[i],buf2, sizeof(buf2), 0);
53 printf(" 发送至线程号<%d>成功&#xff01;\n",ThreadID[i]);
54 }
55 }
56 printf(" \n");
57
58
59 flag1:cc &#61; recv(sock, buf3, BUFLEN, 0); //cc为接收的字符数
60 if(cc &#61;&#61; SOCKET_ERROR|| cc &#61;&#61; 0)
61 {
62 (void) time(&now);
63 pts &#61; ctime(&now);
64 sprintf( buf3," 线程号 <%d> 客户
65 sock &#61; NULL;
66 sockets[number] &#61; NULL;
67 CloseHandle(hThread[number]);
68 printf("%s ", buf3);
69 printf("\t将自动把此数据发送给所有客户&#xff01; \n");
70 for(int i&#61;0;i<&#61;number;i&#43;&#43;)
71 {
72 if(sockets[i] !&#61; NULL && sockets[i] !&#61; sock)
73 {
74 (void) send(sockets[i], buf3, sizeof(buf3), 0);
75 printf(" 发送至线程号<%d>成功&#xff01;\n",ThreadID[i]);
76 }
77 }
78 printf(" \n");
79 }
80
81 else if(cc > 0)
82 {
83 (void) time(&now);
84 pts &#61; ctime(&now);
85 sprintf(buf4," 线程号 <%d> 客户
86
87 printf("%s ",buf4);
88 printf("\t将自动把此数据发送给所有客户&#xff01; \n");
89 for(int i&#61;0;i<&#61;number;i&#43;&#43;)
90 {
91 if(sockets[i] !&#61; NULL && sockets[i] !&#61; sock)
92 {
93 (void) send(sockets[i],buf4, sizeof(buf4), 0);
94 printf(" 发送至线程号<%d>成功&#xff01;\n",ThreadID[i]);
95 }
96 }
97 printf(" \n");
98
99 goto flag1;
100 }
101 (void) closesocket(sock);
102
103 return 0;
104 }
105
106
107 /*------------------------------------------------------------------------
108 * main - Iterative TCP server for DAYTIME service
109 *------------------------------------------------------------------------
110 */
111 void main(int argc, char *argv[])
112 /* argc: 命令行参数个数&#xff0c; 例如&#xff1a;C:\> TCPdaytimed 8080
113 argc&#61;2 argv[0]&#61;"TCPdaytimed",argv[1]&#61;"8080" */
114 {
115 int alen; /* from-address length */
116 WSADATA wsadata;
117 char *service &#61; "5050";
118 WSAStartup(WSVERS, &wsadata); //加载 winsock 2.2 library
119 msock &#61; socket(PF_INET, SOCK_STREAM, 0); //生成套接字。TCP协议号&#61;6&#xff0c; UDP协议号&#61;17
120 memset(&Sin, 0, sizeof(Sin));
121 Sin.sin_family &#61; AF_INET;
122 Sin.sin_addr.s_addr &#61; INADDR_ANY; //指定绑定接口的IP地址。INADDR_ANY表示绑定(监听)所有的接口。
123 Sin.sin_port &#61; htons((u_short)atoi(service)); //atoi--把ascii转化为int&#xff0c;htons - 主机序(host)转化为网络序(network), s(short)
124 bind(msock, (struct sockaddr *)&Sin, sizeof(Sin)); // 绑定端口号&#xff08;和IP地址)
125 listen(msock, 5); //队列长度为5
126
127 printf("\t\t\t\t Chat 多人聊天程序 \n");
128 printf("\t\t\t\t (Server) \n");
129 (void) time(&now);
130 pts &#61; ctime(&now);
131 printf("\t\t\t 时间 &#xff1a;%s",pts);
132 number &#61; -1;
133 while(1) //检测是否有按键
134 {
135 alen &#61; sizeof(struct sockaddr);
136 ssock &#61; accept(msock, (struct sockaddr *)&fsin, &alen);
137 number &#43;&#43;;
138 hThread[number] &#61; (HANDLE)_beginthreadex(NULL, 0,Chat,NULL, 0, &threadID);
139 }
140 (void) closesocket(msock);
141 WSACleanup(); //卸载载 winsock 2.2 library
142 }
Client 部分&#xff1a;
1 /* TCPClient.cpp -- 用于传递struct */
2 #include
3 #include
4 #include
5 #include <string.h>
6 #include
7 #include
8 #include
9 #include
10
11 #define BUFLEN 2000 // 缓冲区大小
12 #define WSVERS MAKEWORD(2, 0) // 指明版本2.0
13 #pragma comment(lib,"ws2_32.lib") // 指明winsock 2.0 Llibrary
14
15 /*------------------------------------------------------------------------
16 * main - TCP client for DAYTIME service
17 *------------------------------------------------------------------------
18 */
19
20 SOCKET sock,sockets[100] &#61; {NULL}; /* socket descriptor */
21 // int cc; /* recv character count */
22 char *packet &#61; NULL; /* buffer for one line of text */
23 char *pts,*input;
24 HANDLE hThread;
25 unsigned threadID;
26
27 unsigned int __stdcall Chat(PVOID PM )
28 {
29 time_t now;
30 (void) time(&now);
31 pts &#61; ctime(&now);
32 char buf[2000];
33
34 while(1)
35 {
36 int cc &#61; recv(sock, buf, BUFLEN, 0); //cc为接收的字符数
37 if(cc &#61;&#61; SOCKET_ERROR|| cc &#61;&#61; 0)
38 {
39 printf("Error: %d.----",GetLastError());
40 printf("与服务器断开连接&#xff01;\n");
41 CloseHandle(hThread);
42 (void)closesocket(sock);
43 break;
44 }
45 else if(cc > 0)
46 {
47 // buf[cc] &#61; &#39;\0&#39;;
48 printf("%s\n",buf);
49 // printf("输入数据&#xff08;exit退出): \n");
50 }
51 }
52 return 0;
53 }
54
55 int main(int argc, char *argv[])
56 {
57 time_t now;
58 (void) time(&now);
59 pts &#61; ctime(&now);
60 char *host &#61; "127.0.0.1"; /* server IP to connect */
61 // char *host &#61; "172.18.33.155";
62 // char *host &#61; "172.18.33.93";
63 // char *host &#61; "172.18.187.1";
64 char *service &#61; "5050"; /* server port to connect */
65 // char *service &#61; "50000";
66 struct sockaddr_in sin; /* an Internet endpoint address */
67 WSADATA wsadata;
68 WSAStartup(WSVERS, &wsadata); /* 启动某版本Socket的DLL */
69
70 memset(&sin, 0, sizeof(sin));
71 sin.sin_family &#61; AF_INET;
72 sin.sin_port &#61; htons((u_short)atoi(service)); //atoi&#xff1a;把ascii转化为int. htons&#xff1a;主机序(host)转化为网络序(network), s--short
73 sin.sin_addr.s_addr &#61; inet_addr(host); //如果host为域名&#xff0c;需要先用函数gethostbyname把域名转化为IP地址
74
75 sock &#61; socket(PF_INET, SOCK_STREAM,0);
76
77 connect(sock, (struct sockaddr *)&sin, sizeof(sin));
78
79 printf("\t\t\t\tChat 多人聊天程序 \n");
80 printf("\t\t\t\t (Client) \n");
81 hThread &#61; (HANDLE)_beginthreadex(NULL, 0,Chat, NULL, 0, &threadID);
82 printf(" \t\t\t\t 【您可以自由发言】\n\n");
83 while(1)
84 {
85 char buf1[2000];
86
87 // scanf("%s",&buf1);
88
89 gets_s(buf1);
90 if(!strcmp(buf1 ,"exit"))
91 goto end;
92
93 (void) send(sock,buf1, sizeof(buf1), 0);
94 (void) time(&now);
95 pts &#61; ctime(&now);
96 printf(" 发送成功&#xff01; ------时间&#xff1a; %s\n",pts);
97 }
98
99 end: CloseHandle(hThread);
100 closesocket(sock);
101 WSACleanup(); /* 卸载某版本的DLL */
102
103 printf("按回车键继续...");
104 getchar();
105 return 0; /* exit */
106 }