局域网实时聊天系统.docx
《局域网实时聊天系统.docx》由会员分享,可在线阅读,更多相关《局域网实时聊天系统.docx(9页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、精选优质文档-倾情为你奉上局域网实时聊天系统1、 图形界面的设置:使用MFC应用程序框架设计局域网聊天系统的图形界面(对话框),使用的Windows标准控件包括:按钮、静态文本、IP地址控件、分组框、编辑框、列表框等控件。本系统集服务器和客户端为一体,通过网络设置按键弹出具体设置页面,通过单选按钮进行单项设置:服务器端:本地监听端口,用于监听客户端的连接信息; 开启按键和停止按键,用于强制服务器的开启和停止。客户端:服务器的IP设置和服务器的端口设置,用于连接服务器;连接服务器按键和停止按键,用于主动加入和退出聊天系统。聊天记录编辑框:默认只读,用于显示聊天系统中各客户端和服务器的聊天记录;聊
2、天记录输入框:输入信息之后,可点击Enter或者发送信息按键发送信息;关闭窗口:点击按键,可关闭正在执行的对话框;更多功能:可用于聊天系统的其他功能扩展。2、 初始化状态:CheckRadioButton:选择单选按钮中的一个;SetDlgItemText:设置编辑框中显示的字符串;EnableWindow:重载函数,设置控件的启用与关闭;ExtendDiaog:设置四个静态变量m_DlgRectLarge、m_GroupRectLarge:用于保存主对话框和分组框的临时变量;m_DlgRectSmall、m_GroupRectSmall:用于保存主对话框和分组框的改变变量。SetWindow
3、Pos:有ID获得主对话框和分组框的句柄,设置界面的伸缩。3、 开启服务器:(1) 创建监听线程:m_hListenThread = CreateThread(NULL, 0, ListenThreadFunc, this, 0, NULL);l NULL:返回的句柄不能被继承;l 0:新线程堆栈的大小与进程主线程堆栈相同;l ListenThreadFunc:线程开始运行的地址,一般为线程入口函数名;l This:传递给线程启动函数的32位参数;l 0:线程创建后立即执行;若为CREAT_SUSPEND,则挂起不执行;l NULL:存放返回的线程ID。(2) 创建监听线程入口函数:DWORD
4、 WINAPI ListenThreadFunc(LPVOID pParam)CChatRoomDlg *pChatRoom = (CChatRoomDlg *)pParam;/创建监听套接字(IPv4网络协议、流式套接字、TCP协议)pChatRoom-m_ListenSock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);/创建sockaddr_in结构存储IP地址和端口sockaddr_in service;/绑定IP地址和端口到监听套接字bind(pChatRoom-m_ListenSock, (sockaddr*)&service, si
5、zeof(sockaddr_in);/监听申请的连接,等待客户端连接 其中两个参数为:S:用于标识一个已捆绑未连接套接口的描述字。backlog:等待连接队列的最大长度。listen(pChatRoom-m_ListenSock, 5);(3) 使用异步I/O模型防止阻塞connect、accept、recieve或recievefrom这些都是阻塞程序,所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数
6、时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生,则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况读写或是异常。int select(nfds, readfds, writefds, exceptfds, timeout);返回值:准备就绪的描述符数,若超时则返回0,若出错则返回-1。nfds:select监视的数,视进程中打开的文件数而定,一般设为你要监视各文件中的最大文件号加一。(注:nfds并非一定表示监视的文件句柄数。)readfd
7、s:select监视的可读文件句柄集合。writefds: select监视的可写文件句柄集合。exceptfds:select监视的异常文件句柄集合。timeout:本次select()的超时结束时间。当readfds或writefds中映象的文件可读或可写或超时,本次select()就结束返回。程序员利用一组系统提供的宏在select()结束时便可判断哪一文件可读或可写,对Socket编程特别有用的就是readfds。几行相关的宏解释如下:FD_ZERO(fd_set *fdset):清空fdset与所有的联系。FD_SET(int fd, fd_set *fdset):建立文件句柄fd与
8、fdset的联系。FD_CLR(int fd, fd_set *fdset):清除文件句柄fd与fdset的联系。(int fd, fd_set *fdset):检查fdset联系的文件句柄fd是否可读写,当0表示可读写。(4) 非阻塞情况下,在一个套接口接受一个连接SOCKET accept(SOCKET , struct sockaddr FAR *, int FAR *);accept函数主要用于服务器端,一般位于listen函数之后,默认会阻塞进程,直到有一个客户请求连接,建立好连接后,它返回的一个新的套接字 socketfd_new ,此后,服务器端即可使用这个新的套接字socket
9、fd_new与该客户端进行通信,而sockfd 则继续用于监听其他客户端的连接请求。第一个参数:用来标识服务端套接字(也就是listen函数中设置为监听状态的套接字)第二个参数:用来保存客户端套接字对应的“地方”(包括客户端IP和端口信息等), 第三个参数是“地方”的占地大小。返回值:对应客户端套接字标识。实际上是这样的: accept函数指定服务端去接受客户端的连接,接收后,返回了客户端套接字的标识,且获得了客户端套接字的“地方”(包括客户端IP和端口信息等)。这个新的套接字 socketfd_new 与监听套接字sockfd 是什么关系?它所代表的socket对象包含了哪些信息?socke
10、tfd_new是否占用了新的端口与客户端通信?先简单分析一番,由于网站的服务器也是一种TCP服务器,使用的是80端口,并不会因客户端的连接而产生新的端口给客户端服务,该客户端依然是向服务器端的80端口发送数据,其他客户端依然向80端口申请连接。因此,可以判断,socketfd_new 并没有占用新的端口与客户端通信,依然使用的是与监听套接字socketfd_new一样的端口号。那这么说,难道一个端口可以被两个socket对象绑定?当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?首先,一个端口肯定只能绑定一个socket。我认为,服务器端的端口在bind的时候已经绑定到了监听套
11、接字socetfd所描述的对象上,accept函数新创建的socket对象其实并没有进行端口的占有,而是复制了socetfd的本地IP和端口号,并且记录了连接过来的客户端的IP和端口号。那么,当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?客户端发送过来的数据可以分为2种,一种是连接请求,一种是已经建立好连接后的数据传输。由于TCP/IP协议栈是维护着一个接收和发送缓冲区的。在接收到来自客户端的数据包后,服务器端的TCP/IP协议栈应该会做如下处理:如果收到的是请求连接的数据包,则传给监听着连接请求端口的socetfd套接字,进行accept处理;如果是已经建立过连接后的客户
12、端数据包,则将数据放入接收缓冲区。这样,当服务器端需要读取指定客户端的数据时,则可以利用socketfd_new套接字通过recv或者read函数到缓冲区里面去取指定的数据(因为socketfd_new代表的socket对象记录了客户端IP和端口,因此可以鉴别)。(5) 监听到的客户端连接加入消息队列在监听过程中,每接收一个客户端连接便产生一个通信套接字,为保存套接字、IP地址、端口号、套接字句柄等信息,此时设计一个类如下:class CClientItem public:CString m_strIp;SOCKET m_Socket;HANDLE hThread;CChatRoomDlg *
13、m_pMainWnd;CClientItem()m_pMainWnd = NULL;m_Socket = INVALID_SOCKET;hThread = NULL;CClientItem tItem;tItem.m_Socket = accSock;tItem.m_pMainWnd = pChatRoom;tItem.m_strIp = inet_ntoa(clientAddr.sin_addr);INT_PTR idx = pChatRoom-m_ClientArray.Add(tItem);/创建连接的客户端的工作线程,默认挂起状态tItem.hThread = CreateThread
14、(NULL, 0, ClientThreadProc, &(pChatRoom-m_ClientArray.GetAt(idx), CREATE_SUSPENDED, NULL);pChatRoom-m_ClientArray.GetAt(idx).hThread = tItem.hThread;ResumeThread(tItem.hThread);4、 开启客户端:(1)点击开启客户端,创建连接线程m_hConnectThred = CreateThread(NULL, 0, ConnectThreadFunc, this, 0, NULL);(2)创建连接线程入口函数DWORD WINA
15、PI ConnectThreadFunc(LPVOID pParam)CChatRoomDlg *pChatRoom = (CChatRoomDlg *)pParam;/创建连接套接字pChatRoom-m_ConnectSock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);/获取对话框中的IP和端口信息CString strServIp;pChatRoom-GetDlgItemText(IDC_IP_ADDR, strServIp);int iPort = pChatRoom-GetDlgItemInt(IDC_CONNECT_PORT);/I
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 局域网 实时 聊天 系统
限制150内