Windows C语言构建网络聊天室

发布时间 : 星期四 文章Windows C语言构建网络聊天室更新完毕开始阅读

s<输入>:是连接用的socket。

buf、len和flags的含义与作用方法与recvfrom()/connect()中的相同,分别表示接收和发送的数据包字符串的地址、长度和标志。

面向无连接的数据报方式的程序流程图如图1所示:

服务器端

调用WSAStartup()初化Winsock 客户端

调用WSAStartup()初化Winsock 调用socket()创建一个监听Socket 调用socket()创建一个会话Socket 调用bind()为监听Socket指定通讯对象 调用listen()设置等待连接状态 阻塞,等待用户连接 调用accept()接收连接并生成会话socket 调用connect()与服务器端连接 调用send()和recv()进行对话 阻塞,等待用户发送数据 调用send()和recv()进行对话 调用closesocket()关闭socket

调用closesocket()关闭socket 图2面向连接的流方式流程图

分别为服务器端和客户端建立如图3、图4所示对话框:

第 5 页 共 13 页

图3 图4

这是一个单方向传送的面向连接的的流方式聊天程序,源程序附在附件源程序Chat_Room2中,源代码比较简单,就不在这里另作说明了。

三、面向连接的异步模式

在上面的流方式中,函数listen()要等到有客房端的连接请求或是出错时才能返回;recv()函数也要等到有数据发送过来的时候或是出错的时候才能返回。这时,如果网络拥挤或一次发送的数据量过大,交换的数据不能在短时间内传送完, 收发数据的函数就因此不能返回,我们把这种现象叫做阻塞。在阻塞期间,除了等待网络操作完成不能进行任何操作。 为了解决这一问题,Winsock为我们提供了一种异步模式,在这种模式中,函数在被调用后立即返回,Winsock通过函数WSAAsyncSelect()来实现非阻塞通信。方法是,由该函数指定某种网络事件(如有数据到达、可以发送数据、有程序请求连接等),当被子指定的网络事件发生时,由Winsock发送由程序事先约定的消息。程序中就可以根据这些消息做出相应的处理。

WSAAsyncSelect(),它的原型是:

int WSAAsyncSelect (SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent); Socket在这个函数调用中被自动设成非阻塞方式,hWnd是接收Winsock消息的窗口句柄,wMsg是向窗口发出的消息名称,用户可以任意定义。LEvent是被指定的网络事件,如下表所示:

网络事件lEvent 值 说明 FD_READ 希望Socket收到数据时发送读的消息 FD_WRITE 希望Socket发送数据时发送写的消息 FD_OOB 希望OOB data到达时发送到达的消息 FD_ACCEPT 希望有连接到来时发送连接请求的消息 FD_CONNECT 希望完成连接时发送连接完成的消息 FD_CLOSE 希望接收Socket关闭的消息 FD_QOS 希望接收Socket服务质量(QoS)变化的消息 FD_GROUP_QOS 希望接收Socket服务质量(QoS)不变的消息 FD_ROUTING_INTERFACE_CHANGE 希望接收指定的地址路由接口变化的消息 FD_ADDRESS_LIST_CHANGE 希望接收Socket协议族局部地址变化的消息 需要注意的是,WSAAsyncSelect()的设定是针对某一个Socket的,也就是说,只有当被设定为异步模式的Socket事件发生时,才会发送这些信息。如果开启了很多Socket,而要让每个Socket都变成异步模式,那么就必须对每一个Socket都呼叫WSAAsyncSelect()来一一设定。

有了异步模式之后,可建立如下的服务器端和客户端程序,对话框如图5、图6所示:

第 6 页 共 13 页

服务器端和客户端程序分别为: Chat_RoomS.h

#define SER_MESSAGE WM_USER+100 #define MaxNumber 5 int WSA_return; WSADATA WSAData;

SOCKET server_hSocket; SOCKET Listen_hSocket;

struct sockaddr_in server_addr; struct sockaddr_in Listen_addr; int Listen_addrlen=sizeof(Listen_addr); int fromlen=sizeof(server_addr);

BOOL server_bErr; UINT server_uPort; char ShowText[1024]; char InputText[256]; char Receive_Text[256];

SOCKET nSocket[MaxNumber]; char *ClientIP[MaxNumber]; int i; char ComeMsg[30]=\走进聊天室\\r\\n\char LeaveMsg[30]=\离开聊天室\\r\\n\char LeaveMsg1[30]=\异常离开\\r\\n\

BOOL APIENTRY Hostname_ipDlgPro(HWND hDlg,UINT message, WPARAM wParam,LPARAM lParam);

Chat_RoomS.c

#include #include\#include\

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow) { DialogBox(hInstance,(LPCTSTR)\

第 7 页 共 13 页

return(TRUE); }

BOOL APIENTRY Hostname_ipDlgPro(HWND hDlg,UINT message, WPARAM wParam,LPARAM lParam) { switch(message) { case WM_INITDIALOG: WSA_return=WSAStartup(0x0002,&WSAData); if(WSA_return!=0) { MessageBox(NULL,\初始化失败!\警告!\ WSACleanup(); } return TRUE; case SER_MESSAGE: switch(lParam) { case FD_ACCEPT: Listen_hSocket=accept(server_hSocket,(LPSOCKADDR)&Listen_addr,&Listen_addrlen); for(i=0;i0) MessageBox(NULL,\异步模式创建失败!\警告!\ ClientIP[i]=inet_ntoa(Listen_addr.sin_addr); break; } } if(i

第 8 页 共 13 页

联系合同范文客服:xxxxx#qq.com(#替换为@)