使用套接字函数设计网络聊天室
2014-04-29 17:08
441 查看
在18.3.2节中笔者介绍了常用的套接字函数,接下来将利用这些套接字函数设计一个网络聊天室程序。程序由两个实例组成,第1个实例为服务器端,负责接收用户的连接请求,并转发用户信息。第2个实例为客户端,负责连接服务器并发送信息。
服务器端程序设计步骤如下:
ch1806实例位置:mr\18\sl\06
(1)创建一个基于对话框的应用程序,设计对话框资源如图18.11所示。
(2)在对话框的头文件中引用“winsock2.h”头文件,并导入网络库文件。
(3)在应用程序的InitInstance方法中初始化套接字。
(4)在对话框类中定义成员变量,记录服务器套接字和与之连接的客户端套接字信息。
(5)在对话框类的OnInitDialog方法中创建套接字,并初始化数据。
(6)处理“监听”按钮的单击事件,将套接字绑定到本机地址,并开始监听套接字。
(7)向对话框中添加HandleData方法,用于接受客户端的连接,并获得客户端传来的数据,将其转发给其他客户端。
(8)改写对话框类的PreTranslateMessage方法,在服务器套接字中有事件触发时调用HandleData方法。
客户端程序设计步骤如下。
ch1807实例位置:mr\18\sl\07
(1)创建一个基于对话框的工程,设置对话框资源如图18.12所示。
图18.12 客户端设计窗口
(2)在对话框类的头文件中引用“winsock2.h”头文件,并导入“ws2_32.lib”库文件。
(3)在应用程序的InitInstance方法中初始化套接字。
(4)在对话框的OnInitDialog方法中创建套接字。
(5)处理“连接”按钮的单击事件,连接服务器,并设置套接字接收数据时触发的消息。
(6)处理“发送”按钮的单击事件,向服务器发送数据。
(7)向对话框类中添加ReceiveData方法,用于接收从服务器传来的数据。
(8)改写对话框的PreTranslateMessage方法,截获对话框的消息,用于接收数据。
运行程序,效果如图18.13、图18.14、图18.15所示。
图18.13 聊天室服务器
图18.14 客户端窗口1
图18.15 客户端窗口2
【责任编辑:阚书 TEL:(010)68476606】
服务器端程序设计步骤如下:
ch1806实例位置:mr\18\sl\06
(1)创建一个基于对话框的应用程序,设计对话框资源如图18.11所示。
(2)在对话框的头文件中引用“winsock2.h”头文件,并导入网络库文件。
#include "winsock2.h" #pragma comment (lib,"ws2_32.lib") |
WSADATA wsd; WSAStartup(MAKEWORD(2,2),&wsd); |
SOCKET m_server,m_client; SOCKET m_Clients[MAXNUM]; //客户端套接字 int m_CurClient; //当前连接的客户数量 |
//创建套接字 m_server = socket(AF_INET,SOCK_STREAM,0); //将网络中的事件关联到窗口的消息函数中 WSAAsyncSelect(m_server,m_hWnd,20000,FD_WRITE|FD_READ|FD_ACCEPT); m_client = 0; m_serverIP = ""; for (int i = 0; i< MAXNUM;i++) m_Clients[i]= 0; m_CurClient = 0; |
void CServerDlg::OnOK() { //服务器端地址 sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;m_IP.GetWindowText(m_serverIP);//要注意,这里的m_IP是IP控件类型的变量,m_serverIP是CString类型的变量 它们都在类的成员变量中先定义了//设置本机地址 serveraddr.sin_addr.S_un.S_addr = inet_addr(m_serverIP);UpdateData(TRUE); //设置端口号 serveraddr.sin_port = htons(atoi(m_port));//m_port也是CString类型的变量//绑定地址 if (bind(m_server,(sockaddr*)&serveraddr,sizeof(serveraddr))) { MessageBox("绑定地址失败."); return; } //开始监听 listen(m_server,50); } |
void CServerDlg::HandleData() { sockaddr_in serveraddr; char buffer[1024]; int len =sizeof(serveraddr); //接收客户端的数据 int curlink = -1;int num = -1; for (int p = 0;p< MAXNUM; p++) { num= recv(m_Clients[p],buffer,1024,0); if (num != -1) { curlink = p; break; } } buffer[num]= 0; if (num==-1) //接受客户端的连接 { if (m_CurClient < MAXNUM) { m_Clients[m_CurClient] = accept(m_server,(struct sockaddr*) &serveraddr,&len); m_CurClient+=1; } return; }//将接收的数据发送给客户端(这里是程序的核心,服务器端把接收到的数据又发送出去了) for (int j = 0;j< m_CurClient;j++) if (j != curlink) send(m_Clients[j],buffer,num,0); } |
BOOL CServerDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message==20000) { HandleData(); return TRUE; } else return CDialog::PreTranslateMessage(pMsg); } |
ch1807实例位置:mr\18\sl\07
(1)创建一个基于对话框的工程,设置对话框资源如图18.12所示。
图18.12 客户端设计窗口
(2)在对话框类的头文件中引用“winsock2.h”头文件,并导入“ws2_32.lib”库文件。
#include "winsock2.h" #pragma comment (lib,"ws2_32.lib") |
WSADATA wsd; WSAStartup(MAKEWORD(2,2),&wsd); |
m_client = socket(AF_INET,SOCK_STREAM,0); |
void CClientDlg::OnOK() { //服务器端地址 sockaddr_in serveraddr;UpdateData(TRUE); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(m_port); serveraddr.sin_addr.S_un.S_addr = inet_addr(m_IP);if (connect(m_client,(sockaddr*)&serveraddr,sizeof(serveraddr))!=0) { MessageBox("连接失败"); return; } else MessageBox("连接成功"); WSAAsyncSelect(m_client,m_hWnd,1000,FD_READ); CString str,info ; m_name.GetWindowText(str);info.Format("%s------>%s",str,"进入聊天室"); int i = send(m_client,info.GetBuffer(0),info.GetLength(),0); } |
void CClientDlg::OnButton1() { CString str,name,info ; m_name.GetWindowText(name); m_info.GetWindowText(str); if (!name.IsEmpty()&&!str.IsEmpty()) { info.Format("%s说: %s",name,str); //开始发送数据 int i = send(m_client,info.GetBuffer(0),info.GetLength(),0); m_list.AddString(info); m_info.SetWindowText(""); } } |
void CClientDlg::ReceiveData(){ char buffer[1024]; //接收服务器端传来的数据, int num = recv(m_client,buffer,1024,0); buffer[num] = 0; //将接收的数据添加到列表框中 m_list.AddString(buffer); } |
BOOL CClientDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message==1000) { ReceiveData(); return TRUE; } else return CDialog::PreTranslateMessage(pMsg); } |
图18.13 聊天室服务器
图18.14 客户端窗口1
图18.15 客户端窗口2
【责任编辑:阚书 TEL:(010)68476606】
相关文章推荐
- 备忘----创建套接字进行地址和端口进行网络序转换时使用ipv4和ipv6都通用的函数
- 使用 Alphablox 创建 J2EE 网络聊天室
- 线程函数的设计以及MsgWaitForMultipleObjects函数的使用要点
- .Net Remoting 事件回调 Client 函数方法完整实例: C# 实现控制台网络聊天室 (Console Remoting ChatRoom)
- 使用socket()函数创建套接字
- 遇到的问题---Windows socket error: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
- 解决方法:通常每个套接字地址 (协议/网络地址/端口)只允许使用一次
- "通常每个套接字地址(协议/网络地址/端口)只允许使用一次"
- 使用socket实现网络聊天室和私聊功能
- 错误信息:通常每个套接字地址(协议/网络地址/端口)只允许使用一次.
- 使用ConcurrentQueue并发集合来设计网络服务器端
- 使用原生的函数构建一个简单的网络请求
- python程序设计基础4:python函数设计和使用
- APUE笔记---网络IPC:socket套接字使用+聊天程序
- C/C++ socket编程教程之四:使用socket()函数创建套接字
- linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数
- 在vb中使用Iphlpapi.dll获取网络信息 第三章 第一节 IPHLPAPI 的其它函数
- Java使用redis+sse实现带频道的网络聊天室
- Android:关于Android Studio连接手机的各种问题 & 解决“通常每个套接字地址(协议/网络地址/端口)只允许使用一次(10048)”的问题。
- C/C++ socket编程教程之四:使用socket()函数创建套接字