Linux c++ select 示例
来源:互联网 发布:淘宝货源一件代发网 编辑:程序博客网 时间:2024/06/05 03:32
//主程序#include <unistd.h> #include <iostream> #include <sys/socket.h>#include <sys/select.h> #include <arpa/inet.h> #include <stdio.h>#include <string.h>#include "socket.h"int main() { int s32ServerSocket = -1; InitServerSocket(s32ServerSocket); //select模型处理过程 fd_set stCheckFdSet,stBakFdSet; //s32AssignFdMax用于记录已分配socket的最大值int s32AssignFdMax = s32ServerSocket+1;struct timeval stTimeout;FD_ZERO(&stCheckFdSet); FD_ZERO(&stBakFdSet); FD_SET(s32ServerSocket, &stBakFdSet); while (1) { stTimeout.tv_sec = 100; stTimeout.tv_usec = 500000; //stCheckFdSet 是一个输入输出参数 //输入时包含用户感兴趣的描述符 //输出时包含活跃的描述符(用户输入集合中的描述符) //所以每次select都要设置fd_set集合 stCheckFdSet = stBakFdSet; int nRet = ::select(s32AssignFdMax, &stCheckFdSet, NULL, NULL, &stTimeout); if (nRet > 0) { INFO_PRINT("\n"); int s32CurrentFd=0; for (s32CurrentFd=0;s32CurrentFd < s32AssignFdMax+1;s32CurrentFd++) { if (FD_ISSET(s32CurrentFd, &stCheckFdSet))//活跃的描述符 { if(s32ServerSocket == s32CurrentFd)//监听的描述符{sockaddr_in addrRemote = {0}; socklen_t nAddrLen = sizeof(addrRemote); socklen_t NewSocket = ::accept(s32ServerSocket, (sockaddr*)&addrRemote, &nAddrLen); FD_SET(NewSocket, &stBakFdSet); if(s32AssignFdMax < NewSocket){s32AssignFdMax = NewSocket+1;}INFO_PRINT("accept [%d]!\n",NewSocket); } #if 1else //可读的 { char szContent[256]={0}; int nRecv = ::recv(s32CurrentFd, szContent, sizeof(szContent), 0); if (nRecv > 0) { szContent[nRecv] = '\0'; INFO_PRINT("recv %d:%s\n",nRecv, szContent); ::send(s32CurrentFd, szContent, nRecv, 0); } else //异常或关闭的{ ::close(s32CurrentFd); FD_CLR(s32CurrentFd, &stBakFdSet); INFO_PRINT("close[%d]\n",s32CurrentFd);} }#endif} } } else if (nRet == 0) { INFO_PRINT("stTimeout!\n"); } else{ INFO_PRINT("select err!\n"); return -1;; } } ::close(s32ServerSocket); //关闭监听描述符 INFO_PRINT("game over!"); return SUCCESS;}
//socket部分
#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <sys/wait.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include "socket.h"static int gs_s32IdleFd = -1;int InitErrDeal(){/*忽略pipe信号,当客户端关闭socket时,server第一write时会收到RST segment(tcp 传输层)server第二次write时,会收到SIGPIPE(brokenpipe)信号,默认处理是退出TIME_WAIT状态,先close的一端会进入 time_wait状态,内核会在一定的时间内保留socket资源(服务器socket通信设计时,让客户端先close)*/signal(SIGPIPE, SIG_IGN);//避免僵尸进程signal(SIGCHLD, SIG_IGN);gs_s32IdleFd = open("/dev/null", O_RDONLY | O_CLOEXEC);return SUCCESS;}int ProcessErr(const ERR_INFO_S &stErrInfo){switch ( stErrInfo.enErrType){ case ERR_EMFILE: {int *s32pAcceptFd = (int *)(stErrInfo.pvUserData);close(gs_s32IdleFd);gs_s32IdleFd = accept(*s32pAcceptFd, NULL, NULL);close(gs_s32IdleFd);gs_s32IdleFd = open("/dev/null", O_RDONLY | O_CLOEXEC); break; } default: { break; }}return SUCCESS;}int InitServerSocket(int &s32ServerFd){int s32Ret = -1;//SOCK_NONBLOCK 设置成非阻塞模式,类似于fcnt的F_SETL 的 O_NONBLOCK//SOCK_CLOEXEC,类似于fcnt 的F_GETFD 的 FD_CLOEXEC ,设置进程替换(fork)时,socket处于关闭状态 s32ServerFd = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if ( s32ServerFd < 0){SHOW_ERR("\n");return FAILURE;}struct sockaddr_in stServerAddr;memset(&stServerAddr, 0, sizeof(stServerAddr));stServerAddr.sin_family = AF_INET;stServerAddr.sin_port = htons(SERVER_PORT);stServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);//设置地址的可重复利用,用于socket的快速重启int s32OnOff = 1;s32Ret= setsockopt(s32ServerFd, SOL_SOCKET, SO_REUSEADDR, &s32OnOff, sizeof(s32OnOff));if (s32Ret < 0){SHOW_ERR("\n");return FAILURE;}s32Ret = bind(s32ServerFd, (struct sockaddr*)&stServerAddr, sizeof(stServerAddr));if (s32Ret < 0){SHOW_ERR("\n");return FAILURE;}s32Ret = listen(s32ServerFd, SOMAXCONN);if (s32Ret < 0){SHOW_ERR("\n");return FAILURE;}return SUCCESS;}int InitClientSocket(int &s32ClientFd){int s32Ret = FAILURE;s32ClientFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);if (s32ClientFd < 0){SHOW_ERR("\n");}struct sockaddr_in stServerAddr;memset(&stServerAddr, 0, sizeof(stServerAddr));stServerAddr.sin_family = AF_INET;stServerAddr.sin_port = htons(SERVER_PORT);stServerAddr.sin_addr.s_addr = inet_addr(SERVER_IP);s32Ret = connect(s32ClientFd, (struct sockaddr*)&stServerAddr, sizeof(stServerAddr));if (s32Ret < 0){SHOW_ERR("\n");return s32Ret;}struct sockaddr_in stLocalAddr;socklen_t addrlen = sizeof(stLocalAddr);s32Ret = getsockname(s32ClientFd, (struct sockaddr*)&stLocalAddr, &addrlen);if (s32Ret < 0){SHOW_ERR("\n");return s32Ret;}SHOW_SOCKADDR_INFO(stLocalAddr);return SUCCESS;}
//客户端
#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <iostream>#include "socket.h"int main(void){int s32Socket=-1;InitClientSocket(s32Socket);char acSendBuf[1024] = {0};char acRecvBuf[1024] ={0};while (fgets(acSendBuf, sizeof(acSendBuf), stdin) != NULL){::send(s32Socket, acSendBuf, strlen(acSendBuf), 0);::recv(s32Socket, acRecvBuf, sizeof(acRecvBuf), 0); fputs(acRecvBuf, stdout);memset(acSendBuf, 0, sizeof(acSendBuf));memset(acRecvBuf, 0, sizeof(acRecvBuf));}close(s32Socket);return 0;}
阅读全文
0 0
- linux select编程示例
- Linux c++ select 示例
- linux socket的select函数示例
- select 示例
- Linux:C/Socket多路复用select
- Linux:C/Socket多路复用select
- Linux:C/Socket多路复用select
- Linux:C/Socket多路复用select
- Linux:C/Socket多路复用select
- Linux:C/Socket多路复用select
- linux C select函数学习
- Linux网络编程echo简单示例2--select实现
- linux c语言 select函数用法
- linux下c语言select函数用法
- linux下c语言select函数用法
- linux下c语言select函数用法
- linux下c语言select函数用法
- linux c中select使用技巧
- [LintCode]35.翻转链表 ***
- CFgym:Castle(KMP)
- Docker常见操作实战
- ANDROID给文本框设置值后光标在前面
- 6大设计原则之迪米特法则(Law Of Demeter)。
- Linux c++ select 示例
- Python学习笔记(初识webpy)
- tchar.h及TCHAR数据类型介绍
- Integer不能强制转换为String:toString()、(String)和String.valueOf()的区别
- A1077. Kuchiguse (20)
- C语言:程序结构和语序
- kotlin官方文档-1.0入门
- 利用策略枚举对讨厌的Switch Case 语句进行重构
- 数据库管理工具_NavicatPemium_入门使用