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

【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  \t【我的线程号: %d 】\n",pts,threadid); 44         (void) send(sock,buf1, sizeof(buf1), 0);  45         sprintf(buf2," 线程号 <%d> 客户<IP:%s 端口:%d>  enter  \n",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port); 46         printf("%s ",buf2);         47         printf("\t将自动把此数据发送给所有客户! \n"); 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>成功!\n",ThreadID[i]); 54             } 55         } 56         printf(" \n"); 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 !  \n \t\t时间: %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("\t将自动把此数据发送给所有客户! \n"); 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>成功!\n",ThreadID[i]); 76             }             77         } 78     printf(" \n"); 79     } 80  81     else if(cc > 0)  82     { 83         (void) time(&now); 84         pts = ctime(&now); 85     sprintf(buf4," 线程号 <%d> 客户<IP:%s 端口:%d>说 :%s  \n \t\t时间 : %s",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port,buf3,pts); 86      87         printf("%s ",buf4); 88         printf("\t将自动把此数据发送给所有客户! \n"); 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>成功!\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 service109  *------------------------------------------------------------------------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 library119     msock = socket(PF_INET, SOCK_STREAM, 0);              //生成套接字。TCP协议号=6, UDP协议号=17120     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);                                    //队列长度为5126 127     printf("\t\t\t\t Chat 多人聊天程序 \n");128     printf("\t\t\t\t       (Server) \n");129      (void) time(&now);130       pts = ctime(&now);131     printf("\t\t\t  时间 :%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 library142 }
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("与服务器断开连接!\n"); 41         CloseHandle(hThread); 42         (void)closesocket(sock); 43         break; 44     } 45     else if(cc > 0)  46     { 47     //    buf[cc] = ‘\0‘; 48         printf("%s\n",buf); 49     //    printf("输入数据(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 = 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("\t\t\t\tChat 多人聊天程序 \n"); 80     printf("\t\t\t\t       (Client) \n"); 81     hThread = (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 = ctime(&now); 96        printf(" 发送成功! ------时间: %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 }
View Code

 

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