TCP虽然可以实现 IO非阻塞操作,但在实际应用时会对资源是否准备完毕进行循环测试,增加了不必要的CPU占用。

为了解决这种问题,应用多路复用的知识,select()监听信号。相关知识可以参考 linux文件读写 文件锁 select poll 。

服务端:

[cpp] view plain copy print ?
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/time.h>
  7. #include <sys/ioctl.h>
  8. #include <unistd.h>
  9. #include <netinet/in.h>
  10. #define PORT                4321
  11. #define MAX_QUE_CONN_NM         5
  12. #define MAX_SOCK_FD         FD_SETSIZE
  13. #define BUFFER_SIZE         1024
  14. int main(){
  15. struct sockaddr_in server_sockaddr, client_sockaddr;
  16. int sin_size, count;
  17. fd_set inset, tmp_inset;
  18. int sockfd, client_fd, fd;
  19. char buf[BUFFER_SIZE];
  20. if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
  21. perror(”socket”);
  22. exit(1);
  23. }
  24. server_sockaddr.sin_family = AF_INET;
  25. server_sockaddr.sin_port = htons(PORT);
  26. server_sockaddr.sin_addr.s_addr = INADDR_ANY;
  27. bzero(&(server_sockaddr.sin_zero), 8);
  28. int i = 1;
  29. //设置socket的属性
  30. setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
  31. if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1){
  32. perror(”bind”);
  33. exit(1);
  34. }
  35. if(listen(sockfd, MAX_QUE_CONN_NM) == -1){
  36. perror(”listen”);
  37. exit(1);
  38. }
  39. printf(”listening….\n”);
  40. //清空select集合
  41. FD_ZERO(&inset);
  42. //将要检测的文件符加入
  43. FD_SET(sockfd, &inset);
  44. while(1){
  45. tmp_inset = inset;
  46. sin_size=sizeof(struct sockaddr_in);
  47. memset(buf, 0, sizeof(buf));
  48. printf(”run while…\n”);
  49. //程序在此阻塞,select返回一个文件符,并将其他文件符清空
  50. if (!(select(MAX_SOCK_FD, &tmp_inset, NULL, NULL, NULL) > 0)){
  51. perror(”select”);
  52. close(sockfd);
  53. exit(1);
  54. }
  55. printf(”run for…\n”);
  56. for (fd = 0; fd < MAX_SOCK_FD; fd++){
  57. if (FD_ISSET(fd, &tmp_inset) > 0) {
  58. printf(”fd is %d ,socket is %d\n”,fd,sockfd);
  59. if (fd == sockfd){
  60. if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size))== -1){
  61. perror(”accept”);
  62. exit(1);
  63. }
  64. FD_SET(client_fd, &inset);
  65. printf(”New connection from %d(socket)\n”, client_fd);
  66. }else{
  67. if ((count = recv(fd, buf, BUFFER_SIZE, 0)) > 0){
  68. printf(”Received a message from %d: %s\n”, fd, buf);
  69. }else{
  70. close(fd);
  71. FD_CLR(fd, &inset);
  72. printf(”Client %d(socket) has left\n”, fd);
  73. }
  74. }
  75. } /* end of if FD_ISSET*/
  76. } /* end of for fd*/
  77. } /* end if while while*/
  78. close(sockfd);
  79. exit(0);
  80. }
#include <sys/types.h>

include <sys/socket.h>

include <stdio.h>

include <stdlib.h>

include <string.h>

include <sys/time.h>

include <sys/ioctl.h>

include <unistd.h>

include <netinet/in.h>

define PORT 4321

define MAX_QUE_CONN_NM 5

define MAX_SOCK_FD FD_SETSIZE

define BUFFER_SIZE 1024

int main(){
struct sockaddr_in server_sockaddr, client_sockaddr;
int sin_size, count;
fd_set inset, tmp_inset;
int sockfd, client_fd, fd;
char buf[BUFFER_SIZE];

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket");exit(1);
}server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&amp;(server_sockaddr.sin_zero), 8);int i = 1;
//设置socket的属性
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &amp;i, sizeof(i));
if (bind(sockfd, (struct sockaddr *)&amp;server_sockaddr, sizeof(struct sockaddr)) == -1){perror("bind");exit(1);
}if(listen(sockfd, MAX_QUE_CONN_NM) == -1){perror("listen");exit(1);
}
printf("listening....\n");
//清空select集合
FD_ZERO(&amp;inset);

//将要检测的文件符加入 FD_SET(sockfd, &inset);

while(1){tmp_inset = inset;     sin_size=sizeof(struct sockaddr_in);memset(buf, 0, sizeof(buf));printf("run while...\n");//程序在此阻塞,select返回一个文件符,并将其他文件符清空if (!(select(MAX_SOCK_FD, &amp;tmp_inset, NULL, NULL, NULL) &gt; 0)){  perror("select");close(sockfd);exit(1);}printf("run for...\n");for (fd = 0; fd &lt; MAX_SOCK_FD; fd++){if (FD_ISSET(fd, &amp;tmp_inset) &gt; 0) {printf("fd is %d ,socket is %d\n",fd,sockfd);if (fd == sockfd){         if ((client_fd = accept(sockfd, (struct sockaddr *)&amp;client_sockaddr, &amp;sin_size))== -1){perror("accept");exit(1);}FD_SET(client_fd, &amp;inset);printf("New connection from %d(socket)\n", client_fd);}else{if ((count = recv(fd, buf, BUFFER_SIZE, 0)) &gt; 0){printf("Received a message from %d: %s\n", fd, buf);}else{close(fd);FD_CLR(fd, &amp;inset);printf("Client %d(socket) has left\n", fd);}}} /* end of if FD_ISSET*/} /* end of for fd*/
} /* end if while while*/close(sockfd);
exit(0);

}

客户端:

[cpp] view plain copy print ?
  1. <span style=“font-size:18px;”>#include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/ioctl.h>
  7. #include <unistd.h>
  8. #include <netdb.h>
  9. #include <netinet/in.h>
  10. #define PORT    4321
  11. #define BUFFER_SIZE 1024
  12. int main(int argc, char *argv[]){
  13. int sockfd, sendbytes;
  14. char buf[BUFFER_SIZE];
  15. struct hostent *host;
  16. struct sockaddr_in serv_addr;
  17. if(argc < 3){
  18. fprintf(stderr,”USAGE: ./client Hostname(or ip address) Text\n”);
  19. exit(1);
  20. }
  21. if ((host = gethostbyname(argv[1])) == NULL){
  22. perror(”gethostbyname”);
  23. exit(1);
  24. }
  25. memset(buf, 0, sizeof(buf));
  26. sprintf(buf, ”%s”, argv[2]);
  27. if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
  28. perror(”socket”);
  29. exit(1);
  30. }
  31. serv_addr.sin_family = AF_INET;
  32. serv_addr.sin_port = htons(PORT);
  33. serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
  34. bzero(&(serv_addr.sin_zero), 8);
  35. if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1){
  36. perror(”connect”);
  37. exit(1);
  38. }
  39. if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1){
  40. perror(”send”);
  41. exit(1);
  42. }
  43. sleep(30);
  44. close(sockfd);
  45. exit(0);
  46. }
  47. </span>
#include <sys/types.h>

include <sys/socket.h>

include <stdio.h>

include <stdlib.h>

include <string.h>

include <sys/ioctl.h>

include <unistd.h>

include <netdb.h>

include <netinet/in.h>

define PORT 4321

define BUFFER_SIZE 1024

int main(int argc, char *argv[]){
int sockfd, sendbytes;
char buf[BUFFER_SIZE];
struct hostent *host;
struct sockaddr_in serv_addr;

if(argc &lt; 3){fprintf(stderr,"USAGE: ./client Hostname(or ip address) Text\n");exit(1);
}if ((host = gethostbyname(argv[1])) == NULL){perror("gethostbyname");exit(1);
}memset(buf, 0, sizeof(buf));
sprintf(buf, "%s", argv[2]);if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){perror("socket");exit(1);
}serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr *)host-&gt;h_addr);
bzero(&amp;(serv_addr.sin_zero), 8);if(connect(sockfd,(struct sockaddr *)&amp;serv_addr, sizeof(struct sockaddr))== -1){perror("connect");exit(1);
}if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1){perror("send");exit(1);
}
sleep(30);
close(sockfd);
exit(0);

}

本篇博客出自  阿修罗道,转载出处:http://blog.csdn.net/fansongy/article/details/6901322

Linux网络编程(四)相关推荐

  1. Linux 网络编程四(socket多线程升级版)

    //网络编程--客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  2. 【Linux网络编程】TCP三次握手和四次挥手

    00. 目录 文章目录 00. 目录 01. 三次握手 02. 四次挥手 03. 三次握手和四次挥手原因 04. 2MSL 05. 附录 01. 三次握手 在 TCP/IP 协议中,TCP 协议提供可 ...

  3. linux网络编程(四)线程池

    linux网络编程(四)线程池 为什么会有线程池? 实现简单的线程池 为什么会有线程池? 大多数的服务器可能都有这样一种情况,就是会在单位时间内接收到大量客户端请求,我们可以采取接受到客户端请求创建一 ...

  4. 详情讲述Linux网络编程关注的问题丨epoll原理丨reactor模型丨三次挥手丨四次握手丨多线程丨单线程丨C/C++Linux丨C++后端开发

    90分钟搞懂linux网络编程关注的问题 1. 三次挥手,四次握手 2. epoll实现原理剖析 3. reactor模型封装 单线程.多线程以及多进程 视频讲解如下,点击观看: 详情讲述Linux网 ...

  5. 【Linux】一步一步学Linux网络编程教程汇总(更新中......)

    00. 目录 文章目录 00. 目录 01. 基础理论知识 02. 初级编程 03. 高级编程 04. LibEvent库 05. 06. 07. 01. 基础理论知识 [Linux网络编程]网络协议 ...

  6. Linux网络编程---详解TCP

    Linux网络编程---详解TCP的三次握手和四次挥手_shanghx_123的博客-CSDN博客_tcp的协议数据单元被称为 TCP协议详解(TCP报文.三次握手.四次挥手.TIME_WAIT状态. ...

  7. Linux网络编程——黑马程序员笔记

    01P-复习-Linux网络编程 02P-信号量生产者复习 03P-协议 协议: 一组规则. 04P-7层模型和4层模型及代表协议 分层模型结构: OSI七层模型: 物.数.网.传.会.表.应TCP/ ...

  8. Linux网络编程---I/O复用模型之select

    https://blog.csdn.net/men_wen/article/details/53456435 Linux网络编程-I/O复用模型之select 1. IO复用模型 IO复用能够预先告知 ...

  9. linux网络编程(二)TCP通讯状态

    linux网络编程(二)TCP通讯状态 TCP状态转换 为什么需要等待2MSL? 端口复用 TCP状态转换 tcp协议连接开始会经过三次握手,客户端和服务器开始都会处于CLOSED状态 第一次握手:客 ...

  10. linux网络编程(一)网络基础传输知识

    linux网络编程(一)网络传输基础知识 一.什么是协议? 二.使用步骤 典型协议 2.网络应用程序设计模式 C/S模式 B/S模式 优缺点 3.分层模型 4.TCP/IP四层模型 通信过程 5.协议 ...

最新文章

  1. Android 屏幕适配从未如斯简单(8月10日最终更新版)
  2. exception in initAndListen: 12596 old lock file, terminating
  3. unbuntu18 netplan 配置固定IP
  4. 流式计算新贵Kafka Stream设计详解--转
  5. Python的IDE之PyCharm:PyCharm的使用技巧图文教程(修改Pycharm默认风格颜色、编辑器内代码注释区域的颜色、编辑器内的Python Interpreter等)之详细攻略
  6. 解决mysql 1032 主从错误
  7. [导入]c#中的关于string的转换的问题
  8. 将txt文件转换成xlsx文件及用matlab读取xlsx
  9. recv函数返回0_函数VLOOKUP与LOOKUP的PK,大战一触即发 Excel神技能!
  10. Excel导入-----导出(包含所选和全部)操作
  11. 用姿态补偿雷达数据畸变的文字想法
  12. 计算机控制系统中采样速率的选择
  13. php不包含_php 正则 不包含某字符串的正则表达式
  14. IM在线聊天-微聊即时通讯完整源码
  15. 勒索病毒代码python_一份勒索病毒解密工具的整理汇总
  16. ❤️对比PyWinAuto和uiautomation实现微信联系人自动采集❤️
  17. 汽车c语言标准 misra,MATLAB 和 Simulink 中的 MISRA C 支持
  18. 本地计算机的硬件基本配置信息,Windows7系统如何查看硬件的基本配置
  19. 计算机网络:四类数据编码技术
  20. v4l2框架—申请缓存(VIDIOC_REQBUFS)

热门文章

  1. 使用java抓取金山词霸的每日一句
  2. Java期末复习基础知识整理(有点长)
  3. Revit SDK 介绍:ModelessForm_ExternalEvent ModelessForm_IdlingEvent
  4. 遇见未来 | 对话朱贤文: PostgreSQL是一匹即将发力的黑马
  5. AtCoder Beginner Contest 190 D - Staircase Sequences
  6. 基于HL7的HIE平台
  7. Java基础 DAY05
  8. 苹果5完美越狱_checkra1n for Mac(越狱工具)
  9. 视频封面如何消重 修改视频md5 百度网盘
  10. SQL使用函数处理数据