您的位置:首页 > 其它

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

2014-05-30 17:43 549 查看

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



新建一个MFC对话框程序

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



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

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

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



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



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




LRESULT CWSAAsyncSelectDlgDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

return CDialogEx::WindowProc(message, wParam, lParam);

}





服务器端

定义

#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 message, WPARAM wParam, LPARAM 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)socketListen, NULL, NULL);

if (INVALID_SOCKET != socketAccept)

{

CreateSocketInfo(socketAccept);

WSAAsyncSelect(socketAccept, m_hWnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE);

}

break;



case FD_READ:// 接收通知

P_SOCKET_INFO pInfo;

pInfo = GetSocketInfo(wParam);

nRecv = recv(pInfo->socket, chBuf, BUF_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(message, wParam, lParam);

}



// 消息发送按钮

void CWSAAsyncSelectServDlg::OnBnClickedBtnRecvSend()

{

UpdateData(true);



//CString 转 char[]

CStringA strSend;

strSend = m_strSend;

strncpy_s(chBuf, strSend, strSend.GetLength()+1);



int err = send(socketAccept, chBuf, strlen(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(GPTR, sizeof(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_INET, SOCK_STREAM, IPPROTO_TCP);



if (INVALID_SOCKET == socketAccept)

{

return FALSE;

}



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

nErrorCode = WSAAsyncSelect(socketAccept, m_hWnd, WM_SOCKET, FD_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*)&addrAccept, sizeof(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_hIcon, TRUE);

SetIcon(m_hIcon, FALSE);

return TRUE;

}







// 消息发送按钮

void CWSAAsyncSelectClientDlg::OnBnClickedBtnRecvSend()

{

UpdateData(TRUE);

CStringA strInput;

strInput = m_strSend;



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

strncpy_s(chBuf, strInput, strInput.GetLength()+1);



int nErrorCode = 0;

nErrorCode = send(socketAccept, chBuf, 1024, 0);

if (SOCKET_ERROR == nErrorCode)

{

nErrorCode = WSAGetLastError();

return;

}

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

UpdateData(FALSE);

GetDlgItem(IDC_EDT_SEND)->SetFocus();

}











// 消息循环

LRESULT CWSAAsyncSelectClientDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

if (WM_SOCKET == message)

{

if (WSAGETSELECTERROR(wParam))

{

AfxMessageBox(_T("ERROR"));

}

else

{

CString strMsg;



switch (WSAGETSELECTEVENT(lParam))

{

case FD_READ:// 接收通知

recv((SOCKET)wParam, chBuf, BUF_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(message, wParam, lParam);

}







源码下载
http://download.csdn.net/detail/yulinxx/7426575
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: