当前位置: 首页 > news >正文

SOCKET通信阻塞问题解决方案

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>int main()
{
//1.创建监听的套接字int fd =socket(AF_INET,SOCK_STREAM,0);  //IP协议,流式,tcpif (fd==-1){perror("socket");return -1;}//2. 绑定监听套接字与本地IPstruct sockaddr_in saddr;saddr.sin_family =AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;//0.0.0.0 0的大端小端无区别  0地址意味着服务器端会自动读网卡的IP地址int ret = bind(fd, (struct sockaddr*)&saddr,sizeof(saddr));if(ret==-1){perror("bind");return -1;}//3.设置监听ret =listen(fd,128);if(ret==-1){perror("listen");return -1;}//4.阻塞并等待客户端连接struct sockaddr_in caddr;socklen_t addrlen = sizeof(caddr); int cfd =accept(fd,(struct sockaddr*)&caddr, &addrlen);if(ret==-1){perror("accept");return -1;}//连接建立成功
//caddr里的ip和端口都是大端,使用需转成小端 inet_ntop 用于IP地址的转换,而 ntohs 用于端口号的转换char ip[32];printf("客户端IP:%s,端口:%d",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(caddr.sin_port));
//5.通信 传输数据while (1){//接收数据char buff[1024];int len =recv(cfd,buff,sizeof(buff),0);if(len>0){printf("client say:%s\n",buff);send(cfd,buff,len,0);}else if(len==0){printf("客户端已经断开了连接...\n");break;}else{perror("recv");break;}}close(fd);close(cfd);return 0;
}

在上面的代码中用到了三个会引起程序阻塞的函数,分别是:

    accept():如果服务器端没有新客户端连接,阻塞当前进程/线程,如果检测到新连接解除阻塞,建立连接
    read():如果通信的套接字对应的读缓冲区没有数据,阻塞当前进程/线程,检测到数据解除阻塞,接收数据
    write():如果通信的套接字写缓冲区被写满了,阻塞当前进程/线程(这种情况比较少见)

如果需要和发起新的连接请求的客户端建立连接,那么就必须在服务器端通过一个循环调用accept()函数,另外已经和服务器建立连接的客户端需要和服务器通信,发送数据时的阻塞可以忽略,当接收不到数据时程序也会被阻塞,这时候就会非常矛盾,被accept()阻塞就无法通信,被read()阻塞就无法和客户端建立新连接。因此得出一个结论,基于上述处理方式,在单线程/单进程场景下,服务器是无法处理多连接的,解决方案也有很多,常用的有三种:

    使用多线程实现
    使用多进程实现
    使用IO多路转接(复用)实现
    使用IO多路转接 + 多线程实现

参考:服务器并发 | 爱编程的大丙

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Docker(十)-Docker运行elasticsearch7.4.2容器实例
  • mac怎样清理photoshop垃圾的方法 ps清理缓存和垃圾 苹果电脑暂存盘已满怎么清理
  • OpenCV分水岭算法watershed函数的使用
  • React: class 和 style
  • 【瑞芯微RV1126(板端摄像头图像数据采集)】②使用v4l2视频设备驱动框架采集图像数据
  • Go 语言条件变量 Cond
  • 如何找到最快解析速度的DNS
  • netty使用redis发布订阅实现消息推送
  • 【React】深入探索React:表单控制、组件通信、副作用管理、自定义Hook
  • Spring Boot(八十二):SpringBoot通过rsa实现API加密
  • 基于深度学习算法,支持再学习功能,不断提升系统精准度的智慧地产开源了。
  • pdf格式过大怎么样变小 pdf文件过大如何缩小上传 超实用的简单方法
  • 百易云资产管理运营系统 comfileup.php 文件上传致RCE漏洞复现(XVE-2024-18154)
  • ChatGPT的原理和成本
  • 【YOLOv8系列】图像分类篇----通过YOLOv8实现图像分类功能
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • docker-consul
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • iOS 系统授权开发
  • JAVA_NIO系列——Channel和Buffer详解
  • Laravel5.4 Queues队列学习
  • Leetcode 27 Remove Element
  • spring boot下thymeleaf全局静态变量配置
  • TypeScript实现数据结构(一)栈,队列,链表
  • 成为一名优秀的Developer的书单
  • 当SetTimeout遇到了字符串
  • 简单基于spring的redis配置(单机和集群模式)
  • 你真的知道 == 和 equals 的区别吗?
  • 如何解决微信端直接跳WAP端
  • 山寨一个 Promise
  • 使用Gradle第一次构建Java程序
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 学习笔记TF060:图像语音结合,看图说话
  • 主流的CSS水平和垂直居中技术大全
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • raise 与 raise ... from 的区别
  • #NOIP 2014#Day.2 T3 解方程
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (003)SlickEdit Unity的补全
  • (12)Linux 常见的三种进程状态
  • (C语言)fgets与fputs函数详解
  • (Matlab)使用竞争神经网络实现数据聚类
  • (poj1.2.1)1970(筛选法模拟)
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (十三)Maven插件解析运行机制
  • (顺序)容器的好伴侣 --- 容器适配器
  • (一)RocketMQ初步认识
  • (转)memcache、redis缓存
  • (转)菜鸟学数据库(三)——存储过程
  • .FileZilla的使用和主动模式被动模式介绍
  • .naturalWidth 和naturalHeight属性,
  • .NET Core WebAPI中封装Swagger配置
  • .net web项目 调用webService
  • .net 使用ajax控件后如何调用前端脚本
  • .NET运行机制