102.tcp实现多线程连接与群聊(代码片段)

喵小喵~ 喵小喵~     2022-10-21     495

关键词:

  • 协议之间的关系

  • socket在哪

  • socket是什么

 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

  门面模式,用自己的话说,就是系统对外界提供单一的接口,外部不需要了解内部的实现。

  • socket编程的基本流程

 

 

tcp通信实现多线程连接与群聊

服务器端

  • 定义端口以及本地ip地址
    1 #define port 9876
    2 #define ip_addr "192.168.1.102"

     

  • 创建事件以及互斥量

    1 HANDLE event;//事件
    2 HANDLE mutex = NULL;
    1 event = CreateEvent(NULL, TRUE, FALSE, NULL);//第二个参数TRUE表示手动复位
    2     mutex = CreateMutex(NULL, FALSE, NULL);//互相排斥

     

  • 接收连接

     1 //接受连接
     2 void recv_connect(void *p)
     3 
     4     WSADATA WSA;//对比版本
     5 
     6     SOCKET client,sever;//客户端
     7 
     8     //本地地址信息,以及连接的客户端地址信息
     9     struct sockaddr_in localeaddr,clientaddr;
    10     int addrlength = 0;
    11     HANDLE hthread1 = NULL;//线程句柄
    12     HANDLE hthread2 = NULL;
    13     HANDLE hthread3 = NULL;
    14     int Ret = 0;
    15     char senbuf[256] =  0 ;
    16 
    17     //对比版本
    18     if (WSAStartup(MAKEWORD(2, 2), &WSA) != 0)
    19     
    20         puts("版本不一致,通信失败");
    21         system("pause");
    22         return;
    23     
    24     //创建通信
    25     sever = socket(AF_INET, SOCK_STREAM, 0);
    26     if (sever == INVALID_SOCKET)
    27     
    28         puts("服务器创建失败");
    29         system("pause");
    30         return;
    31     
    32     //设置服务器结构体信息
    33     localeaddr.sin_family = AF_INET;
    34     localeaddr.sin_addr.s_addr = inet_addr(ip_addr);
    35     localeaddr.sin_port = htons(port);
    36     memset(localeaddr.sin_zero, 0x00, 8);//清零
    37     //与socket绑定
    38     Ret = bind(sever, (struct sockaddr*)&localeaddr, sizeof(localeaddr));
    39     if (Ret != 0)
    40     
    41         puts("绑定失败");
    42         system("pause");
    43         return;
    44     
    45     Ret = listen(sever, 5);
    46     if (Ret != 0)
    47     
    48         puts("监听失败");
    49         system("pause");
    50         return;
    51     
    52     puts("服务器启动");
    53 
    54     while (1)
    55     
    56         addrlength = sizeof(clientaddr);//获取长度
    57         //接受客户端连接,信息存放在clientaddr中
    58         client = accept(sever, (struct sockaddr*) &clientaddr, &addrlength);
    59         if (client == INVALID_SOCKET)
    60         
    61             puts("接收失败");
    62             system("pause");
    63             return;
    64         
    65         printf("\\n客户端连接%s  端口号:%d\\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
    66         //创建写的线程
    67         hthread3 = CreateThread(NULL, 0, clientthreadwrite, (void*)client, 0, NULL);
    68     
    69 
    70     //关闭socket
    71     closesocket(sever);
    72     closesocket(client);
    73     WSACleanup();
    74 

     

  • 向客户端发送消息的多线程函数

     1 //创建线程向客户端发送消息
     2 DWORD WINAPI clientthreadwrite(void *p)
     3 
     4     SOCKET client = (SOCKET)p;//数指针类型转换
     5     int Ret = 0;
     6 
     7     while (1)
     8     
     9         WaitForSingleObject(event, INFINITE);//等待事件
    10         WaitForSingleObject(mutex, INFINITE);
    11         
    12         if (strlen(sendbuf) != 0)
    13         
    14             //发送信息
    15             Ret = send(client, sendbuf, strlen(sendbuf), 0);
    16         
    17         ReleaseMutex(mutex);
    18         ResetEvent(event);//手动复位
    19     
    20 

     

  • 从客户端接收消息的多线程函数

     1 DWORD WINAPI clientthreadread(void *p)
     2 
     3     //数指针类型转换
     4     SOCKET client = (SOCKET)p;
     5     int Ret = 0;
     6     char receivebuf[256];
     7 
     8     while (1)
     9     
    10         //清零
    11         memset(receivebuf, 0, 256);
    12         //读取
    13         Ret = recv(client, receivebuf, 256, 0);
    14         if (Ret == SOCKET_ERROR)
    15         
    16             puts("客户端send失败");
    17             break;
    18         
    19         printf("\\n收到%s,", receivebuf);    
    20         //进入临界区
    21         WaitForSingleObject(mutex, INFINITE);
    22         memset(sendbuf, 0, 256);
    23         //全局变量,锁定
    24         strcpy(sendbuf, receivebuf);
    25         ReleaseMutex(mutex);
    26         //通知
    27         SetEvent(event);
    28     
    29     return 0;
    30 

     

      
  • main函数
     1 void main()
     2 
     3     event = CreateEvent(NULL, TRUE, FALSE, NULL);//第二个参数TRUE表示手动复位
     4     mutex = CreateMutex(NULL, FALSE, NULL);//互相排斥
     5 
     6     _beginthread(recv_connect, 0, NULL);
     7 
     8     Sleep(100);
     9     while (1)
    10     
    11         printf("请输入要发送的信息:");
    12         scanf("%s", sendbuf);
    13         SetEvent(event);
    14     
    15     system("pause");
    16 

     

客户端

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include <winsock.h>
 5 #pragma comment(lib,"ws2_32.lib")
 6 
 7 //定义端口号
 8 #define port 9876
 9 //要连接的ip地址
10 #define ip_addr "192.168.1.102"
11 
12 
13 void main()
14 
15     //对比版本
16     WSADATA WSA;
17     //客户端套接字
18     SOCKET client;
19     //服务器信息
20     struct sockaddr_in severaddr;
21     //线程句柄
22     HANDLE hthread = NULL;
23     //保存连接信息
24     int Ret = 0;
25     char senbuf[256] =  0 ;
26 
27     if (WSAStartup(MAKEWORD(2,2),&WSA)!=0)
28     
29         puts("版本不一致,通信失败");
30         system("pause");
31         return;
32     
33     //创建socket
34     client = socket(AF_INET, SOCK_STREAM, 0);
35     if (client == INVALID_SOCKET)
36     
37         puts("客户端创建失败");
38         system("pause");
39 
40     
41     //设置服务器信息
42     severaddr.sin_family = AF_INET;
43     //设置地址
44     severaddr.sin_addr.s_addr = inet_addr(ip_addr);
45     //端口
46     severaddr.sin_port = htons(port);
47     //清空
48     memset(severaddr.sin_zero, 0x00, 8);
49 
50     //连接
51     Ret = connect(client, (struct sockaddr*) &severaddr, sizeof(severaddr));
52     if (Ret!=0)
53     
54         puts("客户端链接失败");
55         system("pause");
56     
57     while (1)
58     
59         //printf("请输入向服务器发送的消息:");
60         //scanf("%s", senbuf);//输入
61         //Ret = send(client, senbuf, strlen(senbuf), 0);//发送
62         //if (Ret==SOCKET_ERROR)
63         //
64         //    puts("客户端send失败");
65         //    system("pause");
66         //
67         char receivebuf[256];
68         memset(receivebuf, 0, 256);//清零
69         Ret = recv(client, receivebuf, 256, 0);
70         printf("收到客户端发送的消息:%s\\n", receivebuf);
71     
72 
73     closesocket(client);
74     WSACleanup();
75 

 

javasocket编程实现群聊(超详细)(代码片段)

Javasocket编程实现群聊最终效果文末有完整代码,创作不易,点个赞再走吧~客户端之间的交流有人退出群聊时,减少在线人数实现流程1、项目结构即原理分析功能实现多客户之间聊天实时统计在线人数图形化界面创建... 查看详情

java编程实例-tcp聊天室代码实现(代码片段)

Tcp多人聊天室实现客户端:功能:数据发送数据接收技术:socket输入流和输出流多线程,客户端功能模块有两个线程聊天方式:群聊私聊私聊方法:@服务器用户id号:msg服务器:功能:数据转发用户注册技术:ServerSocket每一个用户对应的Sock... 查看详情

socket多任务(代码片段)

1.循环版实现多连接2.threading.Thread多线程(传输文件) 3.SockerServer实现多任务3.1ForkingMixIn-多进程(限linux)3.2ThreadingMixIn-多线程3.3ThreadingTCPServer-线程池4.Select模块(单线程实现多线程效果)  1. 循环版实现多连接以... 查看详情

linux下基于tcp协议的群聊系统设计(多线程+select)(代码片段)

...程相关知识点练习Linux下socket、TCP编程练习Linux下pthread、线程编程练习Linux下多路IO检测、select函数使用练习C语言链表使用练习线程间同步与互斥、互斥锁mutex的使用群聊程序分为客户端和服务器两个程序服务器端:运行整个例子... 查看详情

workerman实现群聊(代码片段)

服务端:<?phprequire_once"../vendor/autoload.php";useWorkerman\Worker;$worker=newWorker(‘websocket://0.0.0.0:2345‘);$worker->count=1;$worker->onWorkerStart=function($data)echo"连接开始\n";;$worker- 查看详情

多线程(线程池原理)(代码片段)

背景阿里电面-线程池是如何实现的?这个问题的侧重点是什么?普通的数据库连接池的概念一般是这样的,多个被静态代理或者动态代理生成的数据库连接,直接放到一个池子里,比方说一个队列,这个数据库连接池提供了如... 查看详情

python多线程连接(代码片段)

查看详情

从零开始实现java多线程数据库连接池(附一个神秘的问题)(代码片段)

本例采用mysql数据库,因此请先下载mysql-connection.jar在我们的实际开发中,离不开和数据库打交道。而和数据库的通信,离不开数据库连接。通常用JDBC连接数据库时,需要加载数据驱动,然后再通过接口返回数... 查看详情

一个简单连接池的实现(代码片段)

一个简单的连接池实现前言本人近日正在学习多线程相关的知识,学习线程池的过程中联想到连接池也是一个存在线程安全的复用结构,因此简单探究了连接池相关的实现,该文章用于记录相关的实现思路。为什么需要连接池?... 查看详情

一个简单连接池的实现(代码片段)

一个简单的连接池实现前言本人近日正在学习多线程相关的知识,学习线程池的过程中联想到连接池也是一个存在线程安全的复用结构,因此简单探究了连接池相关的实现,该文章用于记录相关的实现思路。为什么需要连接池?... 查看详情

java实现一个的基于nio的多线程web服务器(代码片段)

代码地址:https://github.com/iyuanyb/webserver实现了静态、动态资源获取;Cookie、Session、HTTP长连接,及Session和HTTP长连接的定时清除;类似SpringMVC的注解式编程,如 @RequestMapping @RequestParam 等,方法中可以根据参数名从前台... 查看详情

多线程实现报表的高效导出(代码片段)

...主要讲述代码层面利用多线程处理的一点小总结。多线程实现的基础知识实现多线程的方式继承Thread类创建线程实现Runnable接口创建线程实现Callable接口创建线程线程池的实现JDK自带的五种线程池的使用场景newSingleThreadExecutor:一... 查看详情

实现多线程(代码片段)

使用多线程的三种方式1、实现Runnable接口2、实现Callable接口3、继承Thread类4、jdk1.5之后,使用Executor线程池实现Runnable和Callable接口只是当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还是需要Thread来调用,... 查看详情

4.基于nio的群聊系统(代码片段)

...法;【1】群聊需求1)编写一个NIO群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞)2)实现多人群聊;3)服务器端:可以监测用户上线, 查看详情

多线程(代码片段)

进程和线程的概念   线程实现  线程有两种实现方式,一种是继承Thread类实现,另外一种是实现Runnable接口实现,两种线程的实现方式,都是要实现run方法做为执行体的,以下分别记录两种线程实现方法的具体... 查看详情

java进阶多线程(代码片段)

文章目录一、多线程1、继承Thread类(方式一)1)实现多线程2)优缺点2、实现Runnable接口(方式二)1)实现多线程2)实现多线程(匿名内部类方式)3)优缺点3、实现Callable、FutureTask接口(方式三)1)实现多线程2... 查看详情

手动搭建i/o网络通信框架2:bio编程模型实现群聊(代码片段)

...手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊  在第一章中运用Socket和ServerSocket简单的实现了网络通信。这一章,利用BIO编程模型进行升级改造,实现群聊聊天室。    如图:当一个客户端请求进来时... 查看详情

java多线程实现的三种方式(代码片段)

文章目录实现多线程方式一:继承Thread类方法介绍实现步骤代码演示思考问题实现多线程方式二:实现Runnable接口Thread构造方法实现步骤代码演示实现多线程方式三:实现Callable接口方法介绍实现步骤代码演示三种实现方式... 查看详情