TCP/IP通信(服务器)

首先建立对话框,上面含有编辑框,启动按钮,取消,发送按钮。
关联变量接收编辑框CString m_rxdata;发送编辑框CString  m_txdata;
在StdAfx.h文件中包含头文件#include<afxsock.h>  //include MFC sock extensions
定义宏#define WM_CLIENT_ACCEPT WM_USER+101
#define WM_CLIENT_READCLOSE WM_USER+102
并定义一个结构体
typedef struct ZyMsg
{
 char msg[100];
 int i;
}Msg;

在头文件中定义如下变量,并定义接收函数并自己添加消息映射
 Msg msg;
 BOOL BindOK;
 SOCKADDR_IN m_sockServerAddr;
 SOCKET ServerSocket;
 SOCKET Client;

LRESULT OnReadClose(WPARAM wParam,LPARAM lParam);
LRESULT OnAccept(WPARAM wParam,LPARAM lParam);
源文件中消息映射
 ON_MESSAGE(WM_CLIENT_ACCEPT,OnAccept)
 ON_MESSAGE(WM_CLIENT_READCLOSE,OnReadClose)
添加启动按钮和发送按钮的消息响应
然后添加代码
void CServerDlg::ServerInit()  //服务器初始化
{
 //初始化绑定服务器
 WSADATA wsaData;
 int ErrorCode;
 if(WSAStartup(MAKEWORD(2,1),&wsaData))  //调用Windows Sockets DLL
 {
  MessageBox("WinSock 无法初始化!");
  WSACleanup();
  return ;
 }
 
 m_rxdata+="服务器开始创建SOCKET";
 UpdateData(FALSE);  //将变量中数据更新到编辑框

 ServerSocket=socket(PF_INET,SOCK_STREAM,0);  //创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信 
 if(INVALID_SOCKET == ServerSocket)
 {
  MessageBox("无法创建服务器socket!");
  return ;
 }

 m_sockServerAddr.sin_addr.S_un.S_addr=INADDR_ANY; //向所有的IP地址发送信息
 m_sockServerAddr.sin_family=AF_INET;
 m_sockServerAddr.sin_port=htons(8001);

 //与选定的端口绑定
 if(SOCKET_ERROR==bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr)))
 {
  MessageBox("无法绑定服务器!");
  return ;
 }
 m_rxdata+="/n服务器端口8001 ";
 UpdateData(FALSE);  //将变量中数据更新到编辑框

 //产生相应传递给窗口的消息为WM_SERVER_ACCEPT,这是自定义消息
 ErrorCode=WSAAsyncSelect(ServerSocket,m_hWnd,WM_CLIENT_ACCEPT,FD_ACCEPT);

 if(SOCKET_ERROR == ErrorCode)
 {
 // MessageBox("WSAAsyncSelect 设定失败!--用于连接请求的消息!");
  return ;
 }
 
 //开始监听客户连接请求
 if(SOCKET_ERROR == listen(ServerSocket,3))
 {
 // MessageBox("服务器监听失败!");
  return ;
 }
 BindOK=TRUE;  //success

 m_rxdata+="/n服务器绑定监听成功";
 UpdateData(FALSE);  //将变量中数据更新到编辑框
 return ;
}

void CServerDlg::OnStart()  //启动
{
 // TODO: Add your control notification handler code here
 ServerInit();  //服务器初始化
}


void CServerDlg::OnBtnSend()  //发送
{
 // TODO: Add your control notification handler code here
 //发送数据
 if(!BindOK)
 {
  MessageBox("无工作站连接,或服务器未启动!");
  return ;
 }
 UpdateData(TRUE);  //将编辑框中数据更新到变量
 strcpy((char*)msg.msg,(LPCTSTR)m_txdata);  //将发送编辑框中的数据拷贝到结构体msg中
 msg.i=0; //变量清零
 if(SOCKET_ERROR==send(Client,(char*)&msg,sizeof(msg),0))  // recv(ServerSocket,buf,sizeof(buf),0);
 {
  MessageBox("发送数据错误!");
  return ;
 }
 else
 {
  m_rxdata+=m_txdata;
 }
 m_txdata.Empty(); //发送编辑框清空
 UpdateData(FALSE); //将变量中的值更新到编辑框

 ((CEdit*)GetDlgItem(IDC_BTN_SEND))->SetActiveWindow();  //
}

void CServerDlg::OnExit()  //退出
{
 // TODO: Add your control notification handler code here
 WSACleanup();
 OnOK();
}

//自定义接收客户机请求的消息   ON_MESSAGE(WM_CLIENT_ACCEPT,OnAccept)
LRESULT CServerDlg::OnAccept(WPARAM wParam, LPARAM lParam)
{
 if(WSAGETSELECTERROR(lParam))
 {
  MessageBox("Error detected to entry into OnServerAccept!");
  return 0L;
 }
 if(WSAGETSELECTEVENT(lParam)==FD_ACCEPT) //如果
 {
  Client = accept(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,0);
  
  if(INVALID_SOCKET == Client)
  {
   MessageBox("Server socket failed to accept connection!");
   return 0L;
  }
  
  WSAAsyncSelect(Client,m_hWnd,WM_CLIENT_READCLOSE,FD_READ | FD_CLOSE);
  BindOK=TRUE;
 }
 
 m_rxdata+="/n有工作站连接!";
 UpdateData(FALSE);  //将变量中数据更新到编辑框

 return 0L;

}

//自定义的关闭与缓冲区有消息
LRESULT CServerDlg::OnReadClose(WPARAM wParam, LPARAM lParam)
{
 if(!BindOK)
 {
  m_rxdata+="/n有数据到达,但没有工作站信息";
  UpdateData(FALSE);  //将变量中数据更新到编辑框
 }

 CString str;
 switch(WSAGETSELECTEVENT(lParam))
 {
 case FD_READ:
  if(SOCKET_ERROR == recv(Client,(char *)&msg,sizeof(msg),0))
  {
   m_rxdata+="/n接受数据发生错误";
   UpdateData(FALSE);  //将变量中数据更新到编辑框
   return 0L;
  }
  str.Format("%s",msg.msg);
  m_rxdata+=str;
  UpdateData(FALSE);  //将变量中数据更新到编辑框
  break;
 case FD_CLOSE:
  str=_T("/n工作站退出");
  m_rxdata=str;
  closesocket(Client);
  BindOK=FALSE;
  UpdateData(FALSE);  //将变量中数据更新到编辑框
  break;
 }
 return 0L;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值