WSAAsyncselect 模型中,服务器与客户端消息的收发

WSAAsyncselect 模型中,服务器与客户端消息的收发

WSAAsyncselect 模型中,服务器与客户端消息的收发_第1张图片



新建一个MFC对话框程序

服务器与客户端的对话框基本一致,以服务器为例:

 

WSAAsyncselect 模型中,服务器与客户端消息的收发_第2张图片


将左右两个编辑框设置为多行显示. 编辑框属性: 

CEdit 的属性进行设置:Auto HScroll 设置为 False

MultiLine 设置为 True;Want Return 设置为 True

 

分别将其定义一个变量  CString m_strSend;CString m_strRecv;

 

将服务器与客户端的对话框内重写消息处理函数

 WSAAsyncselect 模型中,服务器与客户端消息的收发_第3张图片

 

 

LRESULT CWSAAsyncSelectDlgDlg::WindowProc(UINT messageWPARAM wParamLPARAM lParam)

{

return CDialogEx::WindowProc(messagewParamlParam);

}

 

 

服务器端

定义

#include <WinSock2.h>

#pragma comment(lib"ws2_32.lib")

 

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

 

#define WM_SOCKET  (WM_USER+100)// 消息定义

#define BUF_SIZE 1024// 缓冲区大小

 

SOCKET socketListen;// 监听SOCKET

SOCKET socketAccept;// 连接SOCKET

 

typedef struct _SOCKET_INFO// SOCKET结构体

{

SOCKET socket;

WSABUF wsaBuf;

char chBuf[BUF_SIZE];

_SOCKET_INFO *pNext;

}SOCKET_INFO, *P_SOCKET_INFO;

 

P_SOCKET_INFO pInfoTemp;

void CreateSocketInfo(SOCKET socket);

P_SOCKET_INFO GetSocketInfo(SOCKET socket);

 

char chBuf[BUF_SIZE];

 

 

 

// 消息循环

LRESULT CWSAAsyncSelectServDlg::WindowProc(UINT messageWPARAM wParamLPARAM lParam)

{

switch(message)

{

case WM_SYSCOMMAND:

if (SC_CLOSE == wParam)

{

closesocket(socketAccept);

closesocket(socketListen);

WSACleanup();

}

break;

 

case WM_SOCKET:

if (WSAGETSELECTERROR(wParam))// 错误检查

{

AfxMessageBox(_T("ERROR!"));

}

else

{

int nRecv = 0;

switch (WSAGETSELECTEVENT(lParam))// 事件判断

{

case FD_ACCEPT:// 连接通知

socketAccept = accept((SOCKET)socketListenNULLNULL);

if (INVALID_SOCKET != socketAccept)

{

CreateSocketInfo(socketAccept);

WSAAsyncSelect(socketAcceptm_hWndWM_SOCKETFD_READ | FD_WRITE | FD_CLOSE);

}

break;

 

case FD_READ:// 接收通知

P_SOCKET_INFO pInfo;

pInfo = GetSocketInfo(wParam);

nRecv = recv(pInfo->socketchBufBUF_SIZE, 0);

if (nRecv>0)

{

m_strRecv += chBuf;

m_strRecv += _T("\r\n");

UpdateData(FALSE);

}

break;

 

case FD_WRITE:// 发送通知

break;

 

case FD_CLOSE:

pInfo = GetSocketInfo(wParam);

{

CString strTemp;

strTemp.Format(_T("客户端 %d 已关闭"), pInfo->socket);

AfxMessageBox(strTemp);

}

break;

default:

break;

}

}

}

return CDialogEx::WindowProc(messagewParamlParam);

}

 

// 消息发送按钮

void CWSAAsyncSelectServDlg::OnBnClickedBtnRecvSend()

{

UpdateData(true);

 

//CString 转 char[]

CStringA strSend;

strSend = m_strSend;

strncpy_s(chBufstrSendstrSend.GetLength()+1);

 

int err = send(socketAcceptchBufstrlen(chBuf), 0);

if (SOCKET_ERROR == err)

{

MessageBox(_T("send error!"));

}

m_strSend = _T("");// 编辑框清空

UpdateData(false);

}

 

// 获取SOCKET信息

void CreateSocketInfo(SOCKET socket)

{

P_SOCKET_INFO pInfo;

if (NULL == (pInfo = (P_SOCKET_INFO)GlobalAlloc(GPTRsizeof(SOCKET_INFO) )))

{

return;

}

pInfo->socket = socket;

pInfo->pNext = pInfoTemp;

 

pInfoTemp = pInfo// 把pInfo放到pInfoTemp的第1位

int m = 8;

}

 

 

P_SOCKET_INFO GetSocketInfo(SOCKET socket)

{

P_SOCKET_INFO pInfo = pInfoTemp;

while (pInfo)

{

if (socket == pInfo->socket)

{

return pInfo;

}

pInfo = pInfo->pNext;

}

return NULL;

}

 


客户端

 

定义:

#include <WinSock2.h>

#pragma comment(lib"ws2_32.lib")

#define  WM_SOCKET (WM_USER+101)

SOCKET socketAccept;

#define BUF_SIZE 1024

char chBuf[BUF_SIZE];

 

 

 

OnInitDialog()中,将客户端与服务器进行连接

 

BOOL CWSAAsyncSelectClientDlg::OnInitDialog()

{

int nErrorCode = 0;

WSADATA wsaData;

nErrorCode = WSAStartup(0x0202, &wsaData);

 

socketAccept = socket(AF_INETSOCK_STREAMIPPROTO_TCP);

 

if (INVALID_SOCKET == socketAccept)

{

return FALSE;

}

 

//nErrorCode = WSAAsyncSelect(socketAccept, m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE|FD_CONNECT);

nErrorCode = WSAAsyncSelect(socketAcceptm_hWndWM_SOCKETFD_READ|FD_CLOSE);

 

// 连接

#if 1

sockaddr_in addrAccept;

addrAccept.sin_family = AF_INET;

addrAccept.sin_port = htons(8088);

addrAccept.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

 

while (1) // 因为WSAAsyncSelect 将 socketAccept 置为非阻塞模式

{

nErrorCode = connect(socketAccept, (sockaddr*)&addrAcceptsizeof(sockaddr));

if (SOCKET_ERROR == nErrorCode)

{

nErrorCode = WSAGetLastError();

if (WSAEWOULDBLOCK == nErrorCode || WSAEINVAL == nErrorCode)

{

Sleep(300);

continue;

}

else if (WSAEISCONN == nErrorCode)// 连接成功

{

break;

}

else

{

AfxMessageBox(_T("连接失败"));

return -1;

}

}

}

if (SOCKET_ERROR == nErrorCode)

{

AfxMessageBox(_T("连接失败"));

return FALSE;

}

#endif

 

CDialogEx::OnInitDialog();

 

SetIcon(m_hIconTRUE);

SetIcon(m_hIconFALSE);

return TRUE;

}

 

 

 

// 消息发送按钮

void CWSAAsyncSelectClientDlg::OnBnClickedBtnRecvSend()

{

UpdateData(TRUE);

CStringA strInput;

strInput = m_strSend;

 

memset(chBuf' 'sizeof(char)*1024);

strncpy_s(chBufstrInputstrInput.GetLength()+1);

 

int nErrorCode = 0;

nErrorCode = send(socketAcceptchBuf, 1024, 0);

if (SOCKET_ERROR == nErrorCode)

{

nErrorCode = WSAGetLastError();

return;

}

m_strSend = _T("");// 置空

UpdateData(FALSE);

GetDlgItem(IDC_EDT_SEND)->SetFocus();

}

 

 

 

 

 

// 消息循环

LRESULT CWSAAsyncSelectClientDlg::WindowProc(UINT messageWPARAM wParamLPARAM lParam)

{

if (WM_SOCKET == message)

{

if (WSAGETSELECTERROR(wParam))

{

AfxMessageBox(_T("ERROR"));

}

else

{

CString strMsg;

 

switch (WSAGETSELECTEVENT(lParam))

{

case FD_READ:// 接收通知

recv((SOCKET)wParamchBufBUF_SIZE, 0);

m_strRecv += chBuf;

m_strRecv += _T("\r\n");

UpdateData(FALSE);

break;

case FD_CLOSE:// 关闭通知

strMsg.Format(_T("服务器已关闭 %d"), socketAccept);

AfxMessageBox(strMsg);

break;

case FD_ACCEPT:

case FD_CONNECT:

case FD_WRITE:

break;

}

}

}

 

return CDialogEx::WindowProc(messagewParamlParam);

}

 

 

 

 源码下载

http://download.csdn.net/detail/yulinxx/7426575

你可能感兴趣的:(WSAAsyncselect 模型中,服务器与客户端消息的收发)