今天把《Visual c++游戏开发技术与实例》的“Winsock聊天室”实例中的聊天服务器部分理解了之后剥离
出来自己重新编写了一遍,作为一个独立的项目,然后还是使用原实例中的生成的exe作为客户端使用进行了连
接。成功。
实现了:服务器为同时多个客户端服务,起到转发消息给所有客户端的作用。
在这其中出现了一些不可理解的错误,比如:添加了一个按钮之后,双击按钮编写一个弹出AfxMessageBox,
但可以编译通过,而却不能如预期弹出窗口。后来再添加了按钮,竟然可以了。
还有一处错误,是粗心所致,本来是判断(socket==wParam),但少写一个等号,导致出现的错误是:
编译通过,但在开一个以上的客户端后出现错误。
错误原因是:由于少写一个等号,导致不是判断,而是赋值,判断条件恒成立。导致固定从socket队列中的第一
个socket读取数据,而不是从产生网络事件的socket中读取数据。
要使用winsock异步模式进行编程,要用到一个函数 WSAAsyncSelect,其定义如下:
int WSAAsyncSelect(SOCKET s,HWND hwnd,unsigned int wMsg,long lEvent);
解释:当第一个参数指定的socket上发生了lEvent指定的网络事件,如 有程序请求连接 有数据到达 等事件
(这些事件由第四个参数指定),由WINSOCK对程序(确切说,在本例中,是hwnd指向的窗口)发送由程序事先
约定的消息(即第三个参数wMsg)
一般来说,服务器对以下事件感兴趣:FD_ACCEPT FD_READ
而客户端对一下事件感兴趣:FD_CONNECT FD_READ
对客户端来说,创建一个socket就可以了,所以无须详述。
而对于服务端来说,需要根据情况动态创建/维护1+N个socket(N代表当前连接的客户端数)。
服务器开始监听以后,有个socket专司监听,有FD_ACCEPT网络事件发生后,发送消息给程序(窗口),程序
根据message_map中的对应关系(类似hash表?),找到相应的处理函数名,调用此函数进行处理。此函数将创
建一个对应于客户端的socket,然后将其加入到socket队列中。
在有FD_READ事件到达后,程序遍历socket队列中的所有元素,通过判断wParam从产生网络事件的socket中读
取数据,再遍历socket队列将消息进行转发(群发)。
上述的处理方法好像不太高效,不过目前尚说不出所以然。等到学习了其他i/o模型之后应该能总结出原因。
WSAAsyncSelect模型的优点是在开销不大的情况下可以同时处理许多连接,而select模型需要简历fd_set结构。(其实我还没了解select模型,跳过先:)
缺点是应用程序无论如何至少需要一个窗口,即使程序不需要窗口。
同时,用一个单窗口程序来出来成千上万的套接字中的所有事件,很可能成为性能瓶颈(伸缩性不好)。
以上摘自(windows网络编程)
所以,对于WSAASyncSelect的使用就到今天这个简单的程度即可,接下来进行WSAEventSelect的学习。