前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Chat】实验 -- 实现 C/C++下TCP, 服务器/客户端 "多人聊天室"

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

作者头像
书童小二
发布2018-09-03 18:42:13
1.5K0
发布2018-09-03 18:42:13
举报
文章被收录于专栏:前端儿前端儿

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

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

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

结果大致如:

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

Server 部分:

代码语言:javascript
复制
  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 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("\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 library
142 }

Client 部分:

代码语言:javascript
复制
  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 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014-11-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档