【Chat】实验 -- 实现 C/C++下TCP, 服务器/客户端 "多人聊天室"

本次实验利用TCP/IP, 语言环境为 C/C++

利用套接字Socket编程,以及线程处理,

实现Server/CLient 之间多人的聊天系统的基本功能。

结果大致如:

 

 

下面贴上代码(参考参考...)

Server 部分:

  1 /* TCPdtd.cpp - main, TCPdaytimed */
  2 
  3 #include <stdlib.h>
  4 #include <stdio.h>
  5 #include <winsock2.h>
  6 #include <time.h>
  7 #include "conio.h"
  8 #include <windows.h>
  9 #include <process.h>
 10 #include <math.h>
 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  	【我的线程号: %d 】
",pts,threadid);
 44         (void) send(sock,buf1, sizeof(buf1), 0); 
 45         sprintf(buf2," 线程号 <%d> 客户<IP:%s 端口:%d>  enter  
",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port);
 46         printf("%s ",buf2);        
 47         printf("	将自动把此数据发送给所有客户! 
");
 48         for(int i=0;i<=number;i++)
 49         {            
 50             if(sockets[i] != NULL && sockets[i] != sock)
 51             {
 52             (void) send(sockets[i],buf2, sizeof(buf2), 0); 
 53             printf(" 发送至线程号<%d>成功!
",ThreadID[i]);
 54             }
 55         }
 56         printf(" 
");
 57 
 58 
 59 flag1:cc = recv(sock, buf3, BUFLEN, 0);   //cc为接收的字符数
 60     if(cc == SOCKET_ERROR|| cc == 0)
 61     {
 62         (void) time(&now);
 63         pts = ctime(&now);
 64         sprintf( buf3," 线程号 <%d> 客户<IP:%s 端口:%d>  leave !  
 		时间: %s",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port,pts);
 65         sock = NULL;    
 66         sockets[number] = NULL;
 67         CloseHandle(hThread[number]);
 68         printf("%s ", buf3);        
 69         printf("	将自动把此数据发送给所有客户! 
");
 70         for(int i=0;i<=number;i++)
 71         {            
 72             if(sockets[i] != NULL && sockets[i] != sock)
 73             {
 74             (void) send(sockets[i], buf3, sizeof(buf3), 0);     
 75             printf(" 发送至线程号<%d>成功!
",ThreadID[i]);
 76             }            
 77         }
 78     printf(" 
");
 79     }
 80 
 81     else if(cc > 0) 
 82     {
 83         (void) time(&now);
 84         pts = ctime(&now);
 85     sprintf(buf4," 线程号 <%d> 客户<IP:%s 端口:%d>说 :%s  
 		时间 : %s",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port,buf3,pts);
 86     
 87         printf("%s ",buf4);
 88         printf("	将自动把此数据发送给所有客户! 
");
 89         for(int i=0;i<=number;i++)
 90         {            
 91             if(sockets[i] != NULL && sockets[i] != sock)
 92             {
 93             (void) send(sockets[i],buf4, sizeof(buf4), 0);         
 94             printf(" 发送至线程号<%d>成功!
",ThreadID[i]);
 95             }            
 96         }
 97         printf(" 
");
 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: 命令行参数个数, 例如:C:> TCPdaytimed 8080 
113                      argc=2 argv[0]="TCPdaytimed",argv[1]="8080" */
114 {
115     int     alen;                    /* from-address length               */    
116     WSADATA wsadata; 
117     char    *service = "5050";    
118     WSAStartup(WSVERS, &wsadata);                         //加载 winsock 2.2 library
119     msock = socket(PF_INET, SOCK_STREAM, 0);              //生成套接字。TCP协议号=6, UDP协议号=17
120     memset(&Sin, 0, sizeof(Sin));
121     Sin.sin_family = AF_INET;
122     Sin.sin_addr.s_addr = INADDR_ANY;                    //指定绑定接口的IP地址。INADDR_ANY表示绑定(监听)所有的接口。
123     Sin.sin_port = htons((u_short)atoi(service));        //atoi--把ascii转化为int,htons - 主机序(host)转化为网络序(network), s(short) 
124     bind(msock, (struct sockaddr *)&Sin, sizeof(Sin));   // 绑定端口号(和IP地址)
125     listen(msock, 5);                                    //队列长度为5
126 
127     printf("				 Chat 多人聊天程序 
");
128     printf("				       (Server) 
");
129      (void) time(&now);
130       pts = ctime(&now);
131     printf("			  时间 :%s",pts);
132         number = -1;
133     while(1)                                    //检测是否有按键
134     {                
135         alen = sizeof(struct sockaddr);
136         ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
137         number ++;
138         hThread[number] = (HANDLE)_beginthreadex(NULL, 0,Chat,NULL, 0, &threadID);        
139     }
140     (void) closesocket(msock);
141     WSACleanup();                         //卸载载 winsock 2.2 library
142 }
View Code

Client 部分:

  1 /* TCPClient.cpp  -- 用于传递struct */
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <winsock2.h>
  5 #include <string.h>
  6 #include <time.h>
  7 #include <windows.h>
  8 #include <process.h>
  9 #include <math.h>
 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] = {NULL};                          /* socket descriptor            */
 21 //    int    cc;                                /* recv character count            */
 22     char    *packet = 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 = ctime(&now);
 32        char buf[2000];
 33 
 34 while(1)
 35 {
 36     int cc = recv(sock, buf, BUFLEN, 0);   //cc为接收的字符数
 37     if(cc == SOCKET_ERROR|| cc == 0)
 38     {
 39         printf("Error: %d.----",GetLastError());
 40         printf("与服务器断开连接!
");
 41         CloseHandle(hThread);
 42         (void)closesocket(sock);
 43         break;
 44     }
 45     else if(cc > 0) 
 46     {
 47     //    buf[cc] = '';
 48         printf("%s
",buf);
 49     //    printf("输入数据(exit退出):  
");
 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 = ctime(&now);
 60     char    *host = "127.0.0.1";        /* server IP to connect         */
 61 //    char    *host = "172.18.33.155";
 62 //    char    *host = "172.18.33.93";
 63 //    char    *host = "172.18.187.1";
 64     char *service = "5050";          /* server port to connect       */
 65 //    char *service = "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 = AF_INET;
 72     sin.sin_port = htons((u_short)atoi(service));    //atoi:把ascii转化为int. htons:主机序(host)转化为网络序(network), s--short
 73     sin.sin_addr.s_addr = inet_addr(host);           //如果host为域名,需要先用函数gethostbyname把域名转化为IP地址
 74 
 75     sock = socket(PF_INET, SOCK_STREAM,0);
 76 
 77     connect(sock, (struct sockaddr *)&sin, sizeof(sin));
 78 
 79     printf("				Chat 多人聊天程序 
");
 80     printf("				       (Client) 
");
 81     hThread = (HANDLE)_beginthreadex(NULL, 0,Chat, NULL, 0, &threadID);    
 82     printf(" 				 【您可以自由发言】

");
 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 = ctime(&now);
 96        printf(" 发送成功! ------时间: %s
",pts);
 97 }
 98     
 99 end:    CloseHandle(hThread);
100         closesocket(sock);
101         WSACleanup();                     /* 卸载某版本的DLL */  
102 
103     printf("按回车键继续...");
104     getchar();
105     return 0;                           /* exit */
106 }
View Code
原文地址:https://www.cnblogs.com/imwtr/p/4072452.html