zoukankan      html  css  js  c++  java
  • 【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
  • 相关阅读:
    Django admin修改密码
    Python中查看函数相关文档
    Python之False和None
    前端神器之jquery
    网页三剑客之JS
    Python常用模块-时间模块
    python静态方法和类方法
    数据库学习之MySQL基础
    lmbench的使用方法
    sd卡无法启动及zc706更改主频后可以进入uboot无法启动kernel的坑
  • 原文地址:https://www.cnblogs.com/imwtr/p/4072452.html
Copyright © 2011-2022 走看看