zoukankan      html  css  js  c++  java
  • 104.tcp多线程读写实现群聊

    客户端:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>
     3 #include<stdlib.h>
     4 #include <winsock.h>
     5 #include <process.h>
     6 #pragma comment(lib,"ws2_32.lib")
     7 
     8 #define port 5529
     9 #define ip_addr "192.168.1.108"
    10 
    11 //客户端写的线程
    12 void write(void *p)
    13 {
    14     //指针类型转换
    15     SOCKET client = (SOCKET)p;
    16     while (1)
    17     {
    18         printf("请输入发送的信息:
    ");
    19         char str[256] = { 0 };
    20         scanf("%s", str);
    21         //发送
    22         send(client, str, strlen(str), 0);
    23         Sleep(100);
    24     }
    25 }
    26 
    27 void main()
    28 {
    29     //对比版本
    30     WSADATA WSA;
    31     //客户端套接字
    32     SOCKET client;
    33     //服务器地址
    34     struct sockaddr_in severaddr;
    35     int addrlength = 0;
    36     HANDLE hthread = NULL;//线程句柄
    37     int Ret = 0;;
    38     char senbuf[256] = { 0 };
    39 
    40     //对比版本
    41     if (WSAStartup(MAKEWORD(2,2),&WSA)!=0)
    42     {
    43         puts("版本不一致,通信失败");
    44         system("pause");
    45         return;
    46     }
    47     //创建socket通信
    48     client = socket(AF_INET, SOCK_STREAM, 0);
    49     if (client == INVALID_SOCKET)
    50     {
    51         puts("客户端创建失败");
    52         system("pause");
    53     }
    54     //设置服务器信息
    55     //协议族
    56     severaddr.sin_family = AF_INET;
    57     //设置地址
    58     severaddr.sin_addr.s_addr = inet_addr(ip_addr);
    59     //设置端口
    60     severaddr.sin_port = htons(port);
    61     //清空
    62     memset(severaddr.sin_zero, 0x00, 8);
    63 
    64     //连接到服务器
    65     Ret = connect(client, (struct sockaddr*) &severaddr, sizeof(severaddr));
    66     //判断是否连接成功
    67     if (Ret!=0)
    68     {
    69         puts("客户端连接失败");
    70         system("pause");
    71     }
    72     else
    73     {
    74         puts("客户端连接成功");
    75     }
    76 
    77     //开启一个写的线程
    78     _beginthread(write, 0, (void*)client);
    79     //不断接收信息
    80     while (1)
    81     {
    82         char receivebuf[256];
    83         memset(receivebuf, 0, 256);//清零
    84         Ret = recv(client, receivebuf, 256, 0);
    85         if (strlen(receivebuf)>0)
    86         {
    87             printf("%s
    ", receivebuf);
    88         }
    89     }
    90 
    91     //关闭客户端
    92     closesocket(client);
    93     WSACleanup();
    94 }

    服务器端

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<stdio.h>
      3 #include<stdlib.h>
      4 #include <winsock.h>
      5 #include <process.h>
      6 #pragma comment(lib,"ws2_32.lib")
      7 
      8 //定义端口
      9 #define port 5529
     10 //设置本地ip
     11 #define ip_addr "169.254.29.232"
     12 //发送消息的缓存区
     13 char sendbuf[256] = { 0 };
     14 //事件
     15 HANDLE event=NULL;
     16 //创建互斥量
     17 HANDLE mutex = NULL;
     18 
     19 //保存连接的客户端信息
     20 struct ipinfo
     21 {
     22     SOCKET client;//客户端
     23     struct sockaddr_in clientaddr;
     24 };
     25 
     26 //读取线程是实时的,写入线程是有事件响应的,服务器输入或者收到消息则向客户端发送消息
     27 
     28 //创建线程,用于向客户端发送信息
     29 DWORD WINAPI clientwrite(void *p)
     30 {
     31     //数指针类型转换
     32     SOCKET client = ((struct ipinfo*)p)->client;
     33     //获取连接的客户端信息
     34     struct sockaddr_in clientaddr = ((struct ipinfo*)p)->clientaddr;
     35     int Ret = 0;
     36 
     37     //不断读取
     38     while (1)
     39     {
     40         //等待事件
     41         WaitForSingleObject(event, INFINITE);
     42         //创建互斥量
     43         WaitForSingleObject(mutex, INFINITE);
     44         //判断
     45         if (strlen(sendbuf)!=0)
     46         {
     47             Ret = send(client, sendbuf, strlen(sendbuf), 0);
     48             if (Ret == 0 || Ret == SOCKET_ERROR)
     49             {
     50                 //判断连接的客户端是否退出
     51                 printf("%s,%d退出
    ",inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
     52                 return;
     53             }
     54         }
     55         ReleaseMutex(mutex);
     56         ResetEvent(event);//手动复位
     57     }
     58     return 0;
     59 }
     60 
     61 //创建线程,用于读取客户端写入的信息
     62 DWORD WINAPI clientthreadread(void *p)
     63 {
     64     //数指针类型转换
     65     SOCKET client = ((struct ipinfo*)p)->client;
     66     //获取连接的客户端信息
     67     struct sockaddr_in clientaddr = ((struct ipinfo*)p)->clientaddr;
     68 
     69     int Ret = 0;
     70     //接收到的信息
     71     char receivebufall[256] = {0};
     72     while (1)
     73     {
     74 
     75         char receivebuf[256] = { 0 };
     76         //接收
     77         Ret = recv(client, receivebuf, 256, 0);
     78         if (Ret == 0 ||Ret ==SOCKET_ERROR)
     79         {
     80             printf("%s,%d退出
    ", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
     81             return;
     82         }
     83 
     84         //收到
     85         if (strlen(receivebuf) > 0)
     86         {
     87             memset(receivebufall, 0, 256);
     88             sprintf(receivebufall, "收到%s:来自%s %d
    ", receivebuf, inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
     89             printf("%s", receivebufall);
     90         }
     91 
     92         //互斥量修改全局数据
     93         WaitForSingleObject(mutex, INFINITE);
     94         memset(sendbuf, 0, 256);
     95         strcpy(sendbuf, receivebufall);
     96         ReleaseMutex(mutex);
     97         //收到消息后设置事件,向所有客户端发送消息
     98         SetEvent(event);
     99     }
    100     return 0;
    101 }
    102 
    103 //创建线程
    104 //服务器
    105 void mains(void *p)
    106 {
    107     //对比版本
    108     WSADATA WSA;
    109     //客户端
    110     SOCKET client, sever;
    111     //服务器地址,和连接的客户端信息
    112     struct sockaddr_in localeaddr, clientaddr;
    113     //sockaddr_in的结构体大小
    114     int addrlength = 0;
    115     //线程句柄
    116     HANDLE hthread = NULL;
    117     //发送和接收消息的返回值
    118     int Ret = 0;
    119     char senbuf[256] = { 0 };
    120 
    121     //判断版本
    122     if (WSAStartup(MAKEWORD(2, 2), &WSA) != 0)
    123     {
    124         puts("版本不一致,通信失败
    ");
    125         system("pause");
    126         return;
    127     }
    128     //创建服务器套接字
    129     sever = socket(AF_INET, SOCK_STREAM, 0);
    130     if (sever == INVALID_SOCKET)
    131     {
    132         puts("服务器创建失败
    ");
    133         system("pause");
    134         return;
    135     }
    136     //设置本地的sockaddr_in
    137     localeaddr.sin_family = AF_INET;
    138     localeaddr.sin_addr.s_addr = inet_addr(ip_addr);
    139     localeaddr.sin_port = htons(port);
    140     memset(localeaddr.sin_zero, 0x00, 8);//清零
    141     //socket与sockaddr_in绑定
    142     Ret = bind(sever, (struct sockaddr*)&localeaddr, sizeof(localeaddr));
    143     if (Ret != 0)
    144     {
    145         puts("绑定失败");
    146         system("pause");
    147         return;
    148     }
    149     //开始监听
    150     Ret = listen(sever, 5);
    151     if (Ret != 0)
    152     {
    153         puts("监听失败");
    154         system("pause");
    155         return;
    156     }
    157     puts("服务器启动
    ");
    158 
    159     while (1)
    160     {
    161         //获取长度
    162         addrlength = sizeof(clientaddr);
    163         //通过套接字接受客户端连接
    164         client = accept(sever, (struct sockaddr*) &clientaddr, &addrlength);
    165         if (client == INVALID_SOCKET)
    166         {
    167             puts("接收失败");
    168             system("pause");
    169             return;
    170         }
    171         printf("客户端连接%s  %d
    ", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
    172 
    173         //全局变量pinfo只是起到一个中转的作用,最后结果存放在线程里面
    174         //创建连接的客户端信息
    175         struct ipinfo pinfo;
    176         pinfo.client = client;
    177         pinfo.clientaddr = clientaddr;
    178         //开启一个写的线程
    179         hthread = CreateThread(NULL, 0, clientwrite, (void*)&pinfo, 0, NULL);
    180         //开启一个读的线程
    181         hthread = CreateThread(NULL, 0, clientthreadread, (void*)&pinfo, 0, NULL);
    182     }
    183 
    184     closesocket(sever);
    185     closesocket(client);
    186     WSACleanup();
    187 }
    188 
    189             
    190 
    191 void main()
    192 {
    193     event = CreateEvent(NULL, TRUE, FALSE, NULL);
    194     mutex = CreateMutex(NULL, FALSE, NULL);//排斥
    195     _beginthread(mains, 0, NULL);
    196     while (1)
    197     {    
    198         printf("请输入向客户端发送的信息:");
    199         scanf("%s", sendbuf);
    200         SetEvent(event);
    201     }
    202 
    203     system("pause");
    204 }
  • 相关阅读:
    DeepLearning.aiWeek1Convolution+model++Application
    搭建自己的git服务器
    Deep Neural Networks for Object Detection(翻译)
    VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGESCALE IMAGE RECOGNTION(翻译)
    windows 10下sublime text3环境的搭建以及配置python开发环境
    DeepLearning.aiWeek2Residual Networks
    DeepLearning.aiWeek4Deep Learning & Art: Neural Style Transfer
    同步&异步+阻塞&非阻塞(理解)
    VGGNet学习——实践
    Realtime MultiPerson 2D Pose Estimation using Part Affinity Fields(理解)
  • 原文地址:https://www.cnblogs.com/xiaochi/p/8488580.html
Copyright © 2011-2022 走看看