编程词典
明日图书
明日软件
用户注册
用户登录
站内
  当前位置:编程词典服务网 >> 编程词典社区论坛 >> 基于套接字函数的网络聊...
  · 基于套接字函数的网络聊天系统

用户:  大麦
发帖:  430 篇
作品:  0 个
回复:  110 篇
技术分:  1160 分
等级:  
注册:  2010-05-11 09:09:40



发表于:2010-07-13 15:20:59
          楼主
基于套接字函数的网络聊天系统
利用套接字函数设计一个网络聊天系统。网络聊天系统分为两部分,即客户端和服务器端。客户端用于发送和显示数据,服务器端则用于转发客户端的数据。下面分别介绍客户端和服务器端的设计过程。
1.客户端设计过程如下:
(1)创建一个基于对话框的工程,工程名称为“Client”。设计对话框资源如图1所示。
 
图1  对话框设计窗口
(2)在对话框类的头文件中引用“winsock2.h”头文件,并导入“ws2_32.lib”库文件。
#include "winsock2.h"         //引用头文件
#pragma comment (lib,"ws2_32.lib")       //链接库文件
(3)在应用程序的InitInstance方法中初始化套接字。
WSADATA wsd;          //定义WSADATA对象
WSAStartup(MAKEWORD(2,2),&wsd);      //初始化套接字
(4)改写应用程序的ExitInstance虚方法,在应用程序结束时释放套接字资源。
int CClientApp::ExitInstance()
{
 WSACleanup();          //释放套接字资源
 return CWinApp::ExitInstance();
}
(5)在对话框类中添加如下成员变量。
SOCKET   m_SockClient;        //定义一个套接字
UINT      m_Port;         //定义端口
CString    m_IP;         //定义IP
(6)在对话框初始化时创建套接字。
m_SockClient = socket(AF_INET,SOCK_STREAM,0);   //创建套接字
(7)向对话框中添加ReceiveInfo方法,用于接收服务器端发来的数据。
void CClientDlg::ReceiveInfo()
{
 char buffer[1024];         //定义一个数据缓冲区
 int num = recv(m_SockClient,buffer,1024,0);    //接收数据
 buffer[num] = 0;         //定义结束标记
 m_MsgList.AddString(buffer);       //读取数据到列表中
}
(8)在对话框的消息映射部分添加ON_MESSAGE消息映射宏,将自定义的消息与ReceiveInfo方法关联。
ON_MESSAGE(CM_RECEIVE,ReceiveInfo)     //添加消息映射宏
(9)处理“登录”按钮的单击事件,开始登录服务器。
void CClientDlg::OnLogin()
{
 sockaddr_in serveraddr;        //服务器端地址
 CString strport;          //定义一个字符串,记录端口
 m_ServerPort.GetWindowText(strport);     //获取端口字符串
 m_ServerIP.GetWindowText(m_IP);      //获取IP
 if (strport.IsEmpty() || m_IP.IsEmpty())     //判断端口和IP是否为空
 {
  MessageBox("请设置服务器IP和端口号");   //弹出提示对话框
  return;
 }
 m_Port = atoi(strport);        //将端口字符串转换为整数
 serveraddr.sin_family = AF_INET;      //设置服务器地址家族
 serveraddr.sin_port = htons(m_Port);     //设置服务器端口号
 serveraddr.sin_addr.S_un.S_addr = inet_addr(m_IP);  //设置服务器IP
 //开始连接服务器
 if (connect(m_SockClient,(sockaddr*)&serveraddr,sizeof(serveraddr))!=0)
 {
  MessageBox("连接失败");       //弹出提示对话框
  return;
 } 
 else
  MessageBox("连接成功");       //弹出提示对话框
 WSAAsyncSelect(m_SockClient,m_hWnd,1000,FD_READ); //设置异步模型
 CString strname,info ;        //定义字符串变量
 m_NickName.GetWindowText(strname);     //获取昵称
 info.Format("%s------>%s",strname,"进入聊天室");   //设置发送的信息
 send(m_SockClient,info.GetBuffer(0),info.GetLength(),0);  //向服务器发送数据
}
(10)处理“发送”按钮的单击事件,向服务器发送数据,再由服务器转发数据。
void CClientDlg::OnSend()
{
 CString strData,name,info ;       //定义字符串变量
 m_NickName.GetWindowText(name);     //获取昵称
 m_SendData.GetWindowText(strData);     //获取发送的数据
 if (!name.IsEmpty() && !strData.IsEmpty())    //判断字符串是否为空
 {
  info.Format("%s说: %s",name,strData);    //格式化发送的数据
  send(m_SockClient,info.GetBuffer(0),info.GetLength(),0); //开始发送数据
  m_MsgList.AddString(info);      //向列表中添加数据
  m_SendData.SetWindowText("");     //清空编辑框文本
 }
}
(11)运行程序,效果如图2、图3所示。
 
图2  客户端窗口1
 
图3  客户端窗口2
2.服务器端程序设计步骤如下:
(1)创建一个基于对话框的工程,工程名称为“Server”,设计对话框资源如图4所示。
 
图4  对话框资源设计
(2)在对话框类的头文件中引用“winsock2.h”头文件,并导入“ws2_32.lib”库文件。
#include "winsock2.h"         //引用头文件
#pragma comment (lib,"ws2_32.lib")       //链接库文件
(3)在应用程序的InitInstance方法中初始化套接字。
WSADATA wsd;          //定义WSADATA对象
WSAStartup(MAKEWORD(2,2),&wsd);      //初始化套接字
(4)改写应用程序的ExitInstance虚方法,在应用程序结束时释放套接字资源。
int CServerApp::ExitInstance()
{
 WSACleanup();          //释放套接字资源
 return CWinApp::ExitInstance();
}
(5)向对话框类中添加如下成员变量。
SOCKET m_SockServer,m_SockClient;      //定义套接字
SOCKET m_Clients[MAXNUM];       //客户端套接字
int    m_ConnectNum;         //当前连接的客户数量
CString m_IP;           //定义IP
UINT m_Port;           //定义端口
(6)在对话框初始化时创建套接字。
m_SockServer = socket(AF_INET,SOCK_STREAM,0);   //创建套接字
//将网络中的事件关联到窗口的消息函数中
WSAAsyncSelect(m_SockServer,m_hWnd,WM_USER+1,FD_WRITE|FD_READ|FD_ACCEPT);
m_ConnectNum = 0;          //初始化客户端连接数量
for (int i = 0; i< MAXNUM;i++)        //初始化客户端套接字
 m_Clients[i]= 0;
(7)向对话框中添加TranslateData方法,接收客户端的连接,并转发客户端发来数据。
void CServerDlg::TranslateData()
{
 sockaddr_in serveraddr;        //定义一个网络地址
 char buffer[1024];         //定义一个缓冲区
 int len =sizeof(serveraddr);       //获取网络地址大小
 int curlink = -1;          //定义整型变量
 int num = -1;          //定义整型变量
 for (int i = 0; i < MAXNUM; i++)       //遍历客户端套接字
 {
  num= recv(m_Clients[i],buffer,1024,0);    //获取客户端接收的数据
  if (num != -1)         //判断哪个客户端向服务器发送数据
  {
   curlink = i;         //记录客户端索引
   break;         //终止循环
  }
 }
 buffer[num]= 0;          //设置数据结束标记
 if (num == -1)           //接受客户端的连接
 {
  if (m_ConnectNum < MAXNUM)     //判断当前客户端连接数量是否大于上限
  {
   //接受客户端的连接
   m_Clients[m_ConnectNum] = accept(m_SockServer,(struct sockaddr*)
    &serveraddr,&len);
   m_ConnectNum++;       //将连接数量加1
  } 
  return;
 }
 for (int j = 0; j < m_ConnectNum; j++)     //将接收的数据发送给客户端
  if (j != curlink)         //不向发送方本身发送数据
   send(m_Clients[j],buffer,num,0);
}
(8)在对话框的消息映射部分添加ON_MESSAGE消息映射宏,将消息与TranslateData方法关联。
ON_MESSAGE(WM_USER+1,TranslateData)
(9)处理“设置”按钮的单击事件,绑定套接字到指定的地址上,使套接字处于监听模式。
void CServerDlg::OnSetting()
{
 m_ServerIP.GetWindowText(m_IP);
 CString strPort;
 m_ServerPort.GetWindowText(strPort);
 if (m_IP.IsEmpty() || strPort.IsEmpty())
 {
  MessageBox("请设置服务器IP和端口号","提示");
  return;
 }
 m_Port = atoi(strPort);
 sockaddr_in serveraddr;
 serveraddr.sin_family = AF_INET;
 serveraddr.sin_addr.S_un.S_addr  = inet_addr(m_IP);
 serveraddr.sin_port = htons(m_Port);
 if (bind(m_SockServer,(sockaddr*)&serveraddr,sizeof(serveraddr)))
 {
  MessageBox("绑定地址失败.");
  return;
 }
 listen(m_SockServer,20);
}
(10)运行程序,效果如图5所示。
 
图5  服务器设置窗口
本帖赏分:0 分   回复数:0 篇     
修改   删除   引用   回复
该帖暂无回复!
吉林省明日科技有限公司提供技术支持. 
Copyright © 1999-2008 吉林省明日科技有限公司. 吉ICP备10002740
当前时区 GMT+8, 今天是 
刷新页面 - 关于我们 - 设为首页