Socket初步学习

Socket初步学习:简单的CS模型
主要记录Socket的简单使用
1、初始化准备
 使用AfxSocketInit(WSADATA *lpwsaData = NULL);函数初始化,该函数内部条用的是WSAStartup来加载套接字库,且加载的是1.1版本的套接字库。在使用之前需要先在stdafx.h中添加相应的头文件 Afxsock.h。可以在(以MFC对话框程序为例)应用程序的名.cpp文件的InitInstance()中添加:
  if(!AfxSocketInit())
 {
  AfxMessageBox("加载套接字库失败!");
  return FALSE;
 }
2、创建并初始化socket
 可以将此部分封装为一个BOOL类型的函数在第1步之后紧接着调用此函数。为对话框类添加一个私有成员变量m_socket
 m_socket=socket(AF_INET,SOCK_DGRAM,0);//SOCK_DGRAM:UDP协议
 if(INVALID_SOCKET==m_socket)
 {
  MessageBox("套接字创建失败!");
  return FALSE;
 }
 SOCKADDR_IN addrSock;
 addrSock.sin_family=AF_INET;           //指定地址族
 addrSock.sin_port=htons(6000);          //指定端口
 addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY); //指定IP地址

 int retval;
 retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR)); //绑定socket到指定的IP和端口
 if(SOCKET_ERROR==retval)
 {
  closesocket(m_socket);
  MessageBox("绑定失败!");
  return FALSE;
 }
3、接收数据函数
 为了避免recvfrom函数阻塞导致程序暂停,可以将接收数据放在一个单独的线程中完成,多个参数可以作为一个结构体指针传入。先定义一个结构体
 struct RECVPARAM
 {
  SOCKET sock;
  HWND hwnd;
 };
 在Dialog类中添加线程函数定义 static DWORD WINAPI RecvProc(LPVOID lpParameter);
 接收函数的实现:
 DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)
 {
  SOCKET sock=((RECVPARAM*)lpParameter)->sock;
  HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
  delete lpParameter; 

  SOCKADDR_IN addrFrom;
  int len=sizeof(SOCKADDR);

  char recvBuf[200];
  char tempBuf[300];
  int retval;
  while(TRUE)
  {
   retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
   if(SOCKET_ERROR==retval)
    break;
   sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
   ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);        //发送自定义消息,告诉窗口有接收到数据
  }
  return 0;
 }
 需要定义一个自定义消息 #define WM_RECVDATA  WM_USER+1
 然后在OnInitDialog()函数中添加
 InitSocket();
 RECVPARAM *pRecvParam=new RECVPARAM;
 pRecvParam->sock=m_socket;
 pRecvParam->hwnd=m_hWnd;
 HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
 CloseHandle(hThread);
 最后添加自定义消息的处理函数
  afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);
  ON_MESSAGE(WM_RECVDATA,OnRecvData)
  void 类名::OnRecvData(WPARAM wParam,LPARAM lParam)
  {
   CString str=(char*)lParam;
   CString strTemp;
   GetDlgItemText(IDC_EDIT_RECV,strTemp);
   str+="\r\n";
   str+=strTemp;
   SetDlgItemText(IDC_EDIT_RECV,str);
  }
4、发送数据:
 DWORD dwIP;
 ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);

 SOCKADDR_IN addrTo;
 addrTo.sin_family=AF_INET;
 addrTo.sin_port=htons(6000);
 addrTo.sin_addr.S_un.S_addr=htonl(dwIP);

 CString strSend;
 GetDlgItemText(IDC_EDIT_SEND,strSend);
 sendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
 SetDlgItemText(IDC_EDIT_SEND,"");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值