Select 模型的使用 简单聊天室的实现
2010年07月31日
Select 模型的使用,简单聊天室的实现
select模型是一种非阻塞的I/O 模型,他主要是使用select来同时管理多个套接字,如果没有网络事件发生,它边进入等待状态,以便执行同步IO;它的好处在于一个线程可以同时管理多个连接的套接字,这样避免了线程的膨胀。
要使用selcet模型的步骤:
1. 创建socket
2. socket 通过bind绑定本地地址
3. socket 监听
到这里,都是跟阻塞模式的一模一样,下面是不同的
4.设置套接字的模式为阻塞
u_long value=1;
iRet=ioctlsocket(socket_listen,FIONBIO ,&value); 5. 调用select 函数 intselect(
intnfds,
fd_set*readfds,
fd_set*writefds,
fd_set*exceptfds,
const struct timeval*timeout
); 第一个参数是设为0,不管。第二,三,四个参数都是一个套接字的集合,第二个参数是检测套接字的可读性,第三个检测可写性,第四个检查错误。 第五个设置超时时间,如果为NULL,那么永远等待。第二,三,四个参数不能全为NULL,可以允许其中两个为NULL.
失败返回SOCKET_ERROR也就是-1,如果超时返回0
所以,判断是否成功,只要判断返回值是否>0就OK。
select 方法返回后,会在相应的套接字集合fd_set中移除没有网络事件发生的套接字 。
readfds等待的网络事件:
1.如果是监听套接字,那么说明有一个连接未决,需要调用accept
2.如果是普通套接字,有数据可读,需要调用recv
3.如果是普通套接字,连接关闭,重启,或者 中断
writefds等待的网络事件:
1.数据能够发送
2.如果一个非阻塞连接调用正在处理,连接已经成功
exceptfds等待的网络事件:
1.如果一个非阻塞连接调用正在处理,连接失败
2.OOB 数据可读
下面是一个通过Selcet模型来写的类似聊天室的小程序:
服务器端代码: // 启动 选择模型的非阻塞 服务器 bool ServerClass::StartSelectServer(int Type, sockaddr_in sin) { SOCKET socket_listen=socket(AF_INET,Type,0); if (socket_listen==INVALID_SOCKET) { coutsocket失败"socket成功"SOCKET client_socket; sockaddr_in client_addr; int addr_len=sizeof(sockaddr_in); //所有要检测的socket,用来跟selcet后的进行对比 fd_set set_server; FD_ZERO(&set_server); FD_SET(socket_listen,&set_server); fd_set set_read; while (true) { coutsocket set_read=set_server; if (select(0,&set_read,NULL,NULL,NULL)>0) { //cout返回"结果 for (int i=0;isocket添加到set_server中去 //这样以后就可以用selcet检测到 来自客户端的数据了。 FD_SET(client_socket,&set_server); string strTemp=inet_ntoa(client_addr.sin_addr); strTemp.append("::"); char szFormat[20]; strTemp.append( ltoa( ntohs(client_addr.sin_port),szFormat,10)); m_addr_name_map[client_socket]=strTemp; } } else { cout发送给其他的clients DispatchToAllClients(set_read.fd_array[i],strOut); } } else { cout返回"SOCKET,string>来表示对应关系。
同时,为了实现聊天室的效果,也就是一个人发送消息到服务器,服务器应该分发他的这个消息到所有的其他的客户端,所以增加了一个DispatchToAllClients函数
代码如下: // 分发消息到所有的客户端 bool ServerClass::DispatchToAllClients(SOCKET self,string strMessage) { mapSOCKET,string>::iterator iter_begin=m_addr_name_map.begin(); mapSOCKET,string>::iterator iter_end=m_addr_name_map.end(); for (;iter_begin!=iter_end;++iter_begin) { if (iter_begin->first!=self) { //如果不是发送消息的客户端本身,那么发送消息 send(iter_begin->first,strMessage.c_str(),strMessag e.length(),0); } } return true; } 下面是客户端的实现:
客户端通过一个循环来获得用户的输入,如果有输入,并且不是"quit"和"exit",那么就发送消息到服务器。
同时为了接受服务器转发的其他Clients发送的消息,创建了一个线程,也是用select模型来等待服务器的read网络事件,如果等待到了,就recv,实现了对服务器的消息的接收已经本身消息的发送的同时进行。
客户端代码: // 启动客户端 bool ClientClass::StartClient(int Type, sockaddr_in addr) { m_socket_client=socket(AF_INET,Type,0); if (m_socket_client==INVALID_SOCKET) { coutsocket失败"socket成功"发送消息 gets(buffer); str=buffer; if ( (strcmp(str.c_str(),"quit")==0) || (strcmp(str.c_str(),"exit")==0) ) { break; } else { SendMessageToServer(str); } } CloseClient(); return false; } 发送消息到服务器的函数SendMessageToServer实现 // 发送消息到服务器 bool ClientClass::SendMessageToServer(string strMessage) { if (m_socket_client==INVALID_SOCKET) { cout0) { cout发送消息"发送消息"m_socket_client,&set_client); fd_set set_read; //接收消息 char buffer[MAX_PATH]; while (true) { set_read=set_client; if (select(0,&set_read,NULL,NULL,NULL)>0) { for (int i=0;i0) { cout<<buffer<<endl; } } } } }
发表评论
-
《ASCE1885的网络编程》---Winsock APIの套接口I/O处理函数
2012-01-20 09:09 664《ASCE1885的网络编程》-- ... -
MFC: 多人聊天服务器 服务器端之OICPServer类
2012-01-20 09:08 703MFC: 多人聊天服务器 服务器端之OICPServer类 ... -
腾讯公司后台服务器经典面试题
2012-01-20 09:08 706腾讯公司后台服务器经 ... -
linux中select()函数分析
2012-01-20 09:08 598linux中select()函数分析 2 ... -
TOAD快速入门(中文经典)
2012-01-19 14:12 1073TOAD快速入门(中文经典) ... -
ARM经典100问
2012-01-19 14:12 589ARM经典100问 2011年03月13日 第1章 体系 ... -
怎样才能不掉线使炫舞
2012-01-19 14:12 1207怎样才能不掉线使炫舞 ... -
Linux进程间通信
2012-01-19 14:12 722Linux进程间通信 2011年11 ... -
2011-12-4
2012-01-17 04:03 6552011-12-4 2011年12月04日 ... -
linux下服务说明<转>
2012-01-17 04:03 619linux下服务说明 2011年12月13日 我的Cen ... -
2012-1-12
2012-01-17 04:02 5362012-1-12 2012年01月13日 计算机类基础 ... -
计算机CMOS设置详解
2012-01-17 04:02 610计算机CMOS设置详解 2011年05月30日 计算机C ... -
BIOS 设置详解
2012-01-17 04:02 719BIOS 设置详解 2010年11月11日 BIOS 设 ... -
“粤语中字”的虚词使用现象考察
2012-01-16 02:51 696“粤语中字”的虚词使用现象考察 2009年06月08日 ... -
2011-12-18 粤语之一
2012-01-16 02:50 6632011-12-18 粤语之一 2011年12月18日 ... -
yum install lamp
2012-01-16 02:50 682yum install lamp 2011年12月11日 ...
相关推荐
网络聊天室(socket中的select模型) 服务器、客户端 有点像qq群组
C++ 使用select模型的异步SOCKET通信 聊天室,分为服务器和客户端,简单通信模型,初熟悉select模型
基于UDP协议的select模型代码,解决许多初学者,不知道UDP套接字,select模型的疑问!
聊天室主要实现功能有: 采用UDP单播通信方式,包括服务器端和客户端。 首先启动服务器端,客户端通过用户名和密码登录服务器,服务器响应客户端登录并提示有用户登录,此时两个用户就可以进行聊天。 界面设计使用...
自己编的,用最简单的SELECT模型和多线程技术实现的,还有许多不足之处,但是能实现基本的私聊,群聊,服务器广播功能,我会在以后加以改进。
C++网络编程期末作品 Select模型 SOCKET编程 MFC一对多聊天室 MFC套接字编程
select选择模型的聊天程序 聊天室 聊天软件
TCP 一对多通信的程序(MFC 对话框程序),就是服务器端利用Select模型技术, 能同时接收多个客户端的消息, 其次, 服务器端还能将消息群发给所有已连接的客户端, 实现的基本思路 是使用Select模型的套接字集合...
实现登入 广播聊天的功能 tcp/ip 协议 select 函数运用
多人聊天室 支持多人聊天,使用select模型
多人聊天程序, 广域网上聊天室,传送文件。
很不错的代码,对多线程、select异步模型都有应用,对菜鸟我来讲,一边能看懂
....\局域网聊天室 ....\............\Chat_Client ....\............\...........\Chat_Client.aps ....\............\...........\Chat_Client.clw ....\............\...........\Chat_Client.cpp ....\.......
这里是局域网聊天室程序的原码(VC++6 MFC)。 有比较多的中文注释, Server可以接很多的Client。...使用 Select 模型,多线程,自己封装的 Winsock API 类。 希望对初学Winsock的朋友有一点点的帮助。
我们要实现的是简单的聊天室的例子,就是允许多个人同时一起聊天,每个人发送的消息所有人都能接收到,类似于 QQ 群的功能,而不是点对点的 QQ 好友之间的聊天。如下图: 我们要实现的有两部分: Chat Server:...
我大三写的 服务器端 和 客户端 使用select服务器模型 多线程技术 MFC自定义小时的发送 等等技术
socket网络编程,没有选用线程模式,而是选用的异步的select模型。windows下的WSASelect模型,基于消息传递机制,实现了一个服务器和客户端,聊天
8.1 select模型 210 8.2 WSAAsyncSelect异步I/O模型 212 8.3 WSAEventSelect事件选择模型 216 8.4 重叠I/O模型 221 8.4.1 重叠I/O模型的优点 221 8.4.2 重叠I/O模型的基本原理 221 8.4.3 重叠I/O模型的...
udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 Linux网络编程...
udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 ...