Socket的select模型(转)

注意点:发送的时候字节数不要发送…我就悲剧的测试数据发错了,以为哪出问题了思路:1. 初始化一个socket2. 建立一个socket列表用于管理socket3. 将初步连接的socket放入列表中4. 用select判断列表中未处理的socketWin API版本1.USHORT nPort = 4567; // 此服务器监听的端口号// 创建监听套节字 SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(nPort);sin.sin_addr.S_un.S_addr = INADDR_ANY; // 绑定套节字到本地机器 if (::bind(sListen, (sockaddr*)&sin, sizeof (sin)) == SOCKET_ERROR){ printf( " Failed bind() \n" ); return -1;} // 进入监听模式 ::listen(sListen, 5);2.// select模型处理过程// 1)初始化一个套节字集合fdSocket,添加监听套节字句柄到这个集合 fd_set fdSocket; // 所有可用套节字集合 FD_ZERO(&fdSocket);FD_SET(sListen, &fdSocket);3.while (TRUE){ // 2)将fdSocket集合的一个拷贝fdRead传递给select函数, // 当有事件发生时,select函数移除fdRead集合中没有未决I/O操作的套节字句柄,然后返回。 fd_set fdRead = fdSocket; int nRet = ::select(0, &fdRead, NULL, NULL, NULL); if (nRet > 0) { // 3)通过将原来fdSocket集合与select处理过的fdRead集合比较, // 确定都有哪些套节字有未决I/O,并进一步处理这些I/O。 for ( int i=0; i<( int )fdSocket.fd_count; i++) { if (FD_ISSET(fdSocket.fd_array[i], &fdRead)) { if (fdSocket.fd_array[i] == sListen) //(1)监听套节字接收到新连接 { if (fdSocket.fd_count < FD_SETSIZE) { sockaddr_in addrRemote; int nAddrLen = sizeof (addrRemote); SOCKET sNew = ::accept(sListen, (SOCKADDR*)&addrRemote, &nAddrLen); FD_SET(sNew, &fdSocket); printf( "接收到连接(%s)\n" ,::inet_ntoa(addrRemote.sin_addr)); } else { printf( " Too much connections! \n" ); continue ; } } else { char szText[256]; int nRecv = ::recv(fdSocket.fd_array[i],szText, strlen(szText), 0); if (nRecv > 0) // (2)可读 { szText[nRecv] = '\0' ; printf( "接收到数据:%s \n" , szText); } else // (3)连接关闭、重启或者中断 { ::closesocket(fdSocket.fd_array[i]); printf( "关闭\n" ); FD_CLR(fdSocket.fd_array[i],&fdSocket); } } } } } else { printf( " Failed select() \n" ); break ; }}二.自己写了一个c#版本的socket的select方法使用class Threadtcpserver { private Socket server; public Threadtcpserver() { IPAddress local = IPAddress .Parse( "127.0.0.1" ); IPEndPoint iep = new IPEndPoint (local, 4567); server = new Socket ( AddressFamily .InterNetwork, SocketType .Stream, ProtocolType .Tcp); // 将套接字与本地终结点绑定 server.Bind(iep); //在本地13000端口号上进行监听 server.Listen(20); Console .WriteLine( "等待客户机进行连接......" ); List < Socket > socketList = new List < Socket >(); socketList.Add(server); while ( true ) { List < Socket > temp = socketList.ToList(); Socket .Select(temp, null , null , 1000); int count = temp.Count; for ( int i = 0; i < count; i++) { if (temp[i].Equals(server)) { Socket client = socketList[i].Accept(); socketList.Add(client); } else { byte [] bytes = new byte [1024]; int len; if ((len = temp[i].Receive(bytes)) > 0) { Console .WriteLine( "收到数据:" + System.Text. Encoding .UTF8.GetString(bytes, 0, len)); } else { temp[i].Close(); socketList.Remove(temp[i]); Console .WriteLine( "关闭" ); } } } } }}测试:可以多次调用下面函数测试public static void ClientTest(){ Socket client; byte [] buf = new byte [1024]; string input; IPAddress local = IPAddress .Parse( "127.0.0.1" ); IPEndPoint iep = new IPEndPoint (local, 4567); try { client = new Socket ( AddressFamily .InterNetwork, SocketType .Stream, ProtocolType .Tcp); client.Connect(iep); } catch ( SocketException ) { Console .WriteLine( "无法连接到服务器!" ); return ; } input = "test" ; client.Send( Encoding .ASCII.GetBytes(input)); Console .WriteLine( "断开与服务器的连接......" ); client.Close();}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux系统中,socket select模型用于解决大量客户端并发需求中的问题。它是一种多路复用的机制,可以同时监听多个socket文件描述符的可读、可写和异常事件。通过使用select模型,程序可以在一个线程中同时处理多个客户端连接,提高了程序的并发处理能力。 在之前的实践中,可能会遇到select模型在Linux下的一些问题。例如,对于FD_SETSIZE的理解不深刻,以为它是简单的个数而不是一个值。这样的误解可能导致一些阻塞问题。 为了解决这些问题,有些人选择将socket模型select改为epoll。epoll是Linux特有的一种I/O事件通知机制,它使用一个文件描述符来管理多个socket,可以实现更高效的事件监听和处理。可以说,epoll在处理大量并发连接时比select更加高效。 总结起来,socket select模型在Linux系统中是用于解决大量客户端并发需求的一种机制。它通过监听多个socket文件描述符的可读、可写和异常事件,实现了多路复用。在实践中,可能会遇到一些问题,如对FD_SETSIZE的理解不深刻等。为了解决这些问题,一些人选择将socket模型select改为epoll。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [socket网络通信模型select与epoll](https://blog.csdn.net/chenlycly/article/details/123717804)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值