当有客户端连接上来,并发送数据时,服务端一直在提示重叠IO操作进行中
请高手加我QQ 24645955 指点,并结分服务端代码如下
#include "stdafx.h"
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")
#include "proto.h"
#include "iostream.h"
#include "server.h"定义结构体如下
struct stLoginMessage
{
char userName[10];
char password[10];
};//Client 注销时发送消息
struct stLogoutMessage
{
char userName[10];
};struct stUserListNode
{
char userName[10];
unsigned int ip;
unsigned int port;
};//Server Send to Client
struct stServerToClient
{
int iMessageType;
union _message
{
stUserListNode user;
}message;
};//Client 向Server发送消息格式
struct stMessage
{
int iMessageType;
union _message
{
stLoginMessage loginmember;
stLogoutMessage logoutmember;
}message;
};
//IO completion struct
typedef struct{
OVERLAPPED ol;
WSABUF dataBuf;
char buffer[BUFF_SIZE];
DWORD bytesSend;
DWORD bytesRecv;
stMessage stClientToServer;
}PER_IO_OPERATION_DATA,*LP_PER_IO_OPERATION_DATA;
typedef struct
{
SOCKET socket;
}PER_HANDLE_DATA,*LP_PER_HANDLE_DATA;
void InitSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2,2);
int error_flag;
error_flag = WSAStartup(wVersionRequested,&wsaData);
if(error_flag != 0)
{
printf("start error");
}
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wHighVersion != 2))
{
printf("no useble dll");
WSACleanup();//
}
}
SOCKET MakeSocket()
{
SOCKET s;
s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s < 0)
{
printf("create socket error");
}
return s;}
int main(int argc, char* argv[])
{
InitSocket(); SOCKET listener;
SOCKADDR_IN salocal;
listener = MakeSocket();
salocal.sin_family = AF_INET;
salocal.sin_port = htons(SERVER_PORT);
salocal.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listener,(sockaddr *)&salocal,sizeof(sockaddr)) == 0)
{
printf("bind ok");
}
else
{
printf("bind error %d",WSAGetLastError());
} if(listen(listener,300) == 0)
{
printf("listen ok");
}
else
{
printf("listen error %d",WSAGetLastError());
} HANDLE hCompPort;
hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
/*
开启工作线程过数
*/
CreateWorkThread(hCompPort); LP_PER_HANDLE_DATA perHandleData;
LP_PER_IO_OPERATION_DATA perIoOperationData; SOCKET sClient;
while(true)
{
//绑定完成端口
sClient = WSAAccept(listener,NULL,NULL,NULL,0);
printf("socket connect %d",sClient);
if(sClient > 0)
{
printf("wsaaccept OK");
}
else
{
printf("wsaaccept error %d",WSAGetLastError());
}
perHandleData = (LP_PER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
perHandleData->socket = sClient;
CreateIoCompletionPort((HANDLE)sClient,hCompPort,(DWORD)perHandleData,0); //投递一次操作
//填充OVERLAPPED结构
perIoOperationData = (LP_PER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA)); ZeroMemory(&(perIoOperationData->ol),sizeof(OVERLAPPED));
perIoOperationData->bytesSend = 0;
perIoOperationData->bytesRecv = 0;
perIoOperationData->dataBuf.len = BUFF_SIZE;
perIoOperationData->dataBuf.buf = perIoOperationData->buffer;
DWORD flags = 0;
if( 0 == WSARecv(sClient,&(perIoOperationData->dataBuf),1,&(perIoOperationData->bytesRecv),&flags,(LPWSAOVERLAPPED)perIoOperationData,NULL))
{
printf("receive ok");
}
else
{
printf("receiv error %d",WSAGetLastError());
}
}
return 0;
}void CreateWorkThread(LPVOID hCompPort)
{
SYSTEM_INFO systemInfo;
GetSystemInfo(& systemInfo);
int i;
DWORD threadID;
HANDLE threadHandle;
for(i=0;i < systemInfo.dwNumberOfProcessors*2;i++)
{
threadHandle = CreateThread(NULL,0,ServerWorkerThread,hCompPort,0,&threadID);
CloseHandle(threadHandle);
}
}DWORD WINAPI ServerWorkerThread(LPVOID completionPortID)
{
HANDLE hCompPort = (HANDLE)completionPortID;
//处理消息
LP_PER_IO_OPERATION_DATA perIoOperationData;
LP_PER_HANDLE_DATA perHandleData; DWORD dwTransCount = 0;
while(true)//获取消息队列
{
printf("work thread");
if(GetQueuedCompletionStatus(hCompPort,&dwTransCount,(LPDWORD)&perHandleData,(LPOVERLAPPED *)&perIoOperationData,INFINITE) == 0)
{
printf(" GetQueuedCompletionStatus failed with error %d\n " , WSAGetLastError());
}
else
{
printf("get message ok transnum %d",dwTransCount);
}
switch(perIoOperationData->stClientToServer.iMessageType)
{
case REGISTER:
perIoOperationData->stClientToServer.message.loginmember.userName;
break;
case LOGIN:
printf("user name is %s",perIoOperationData->stClientToServer.message.loginmember.userName);
break;
case LOGOUT:
break;
}
printf("type is %d and userName is %s",perIoOperationData->stClientToServer.iMessageType,perIoOperationData->stClientToServer.message.loginmember.userName);
printf("receive io data %d",perIoOperationData->bytesRecv);
return 0;
}}
请高手加我QQ 24645955 指点,并结分服务端代码如下
#include "stdafx.h"
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")
#include "proto.h"
#include "iostream.h"
#include "server.h"定义结构体如下
struct stLoginMessage
{
char userName[10];
char password[10];
};//Client 注销时发送消息
struct stLogoutMessage
{
char userName[10];
};struct stUserListNode
{
char userName[10];
unsigned int ip;
unsigned int port;
};//Server Send to Client
struct stServerToClient
{
int iMessageType;
union _message
{
stUserListNode user;
}message;
};//Client 向Server发送消息格式
struct stMessage
{
int iMessageType;
union _message
{
stLoginMessage loginmember;
stLogoutMessage logoutmember;
}message;
};
//IO completion struct
typedef struct{
OVERLAPPED ol;
WSABUF dataBuf;
char buffer[BUFF_SIZE];
DWORD bytesSend;
DWORD bytesRecv;
stMessage stClientToServer;
}PER_IO_OPERATION_DATA,*LP_PER_IO_OPERATION_DATA;
typedef struct
{
SOCKET socket;
}PER_HANDLE_DATA,*LP_PER_HANDLE_DATA;
void InitSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2,2);
int error_flag;
error_flag = WSAStartup(wVersionRequested,&wsaData);
if(error_flag != 0)
{
printf("start error");
}
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wHighVersion != 2))
{
printf("no useble dll");
WSACleanup();//
}
}
SOCKET MakeSocket()
{
SOCKET s;
s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s < 0)
{
printf("create socket error");
}
return s;}
int main(int argc, char* argv[])
{
InitSocket(); SOCKET listener;
SOCKADDR_IN salocal;
listener = MakeSocket();
salocal.sin_family = AF_INET;
salocal.sin_port = htons(SERVER_PORT);
salocal.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listener,(sockaddr *)&salocal,sizeof(sockaddr)) == 0)
{
printf("bind ok");
}
else
{
printf("bind error %d",WSAGetLastError());
} if(listen(listener,300) == 0)
{
printf("listen ok");
}
else
{
printf("listen error %d",WSAGetLastError());
} HANDLE hCompPort;
hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
/*
开启工作线程过数
*/
CreateWorkThread(hCompPort); LP_PER_HANDLE_DATA perHandleData;
LP_PER_IO_OPERATION_DATA perIoOperationData; SOCKET sClient;
while(true)
{
//绑定完成端口
sClient = WSAAccept(listener,NULL,NULL,NULL,0);
printf("socket connect %d",sClient);
if(sClient > 0)
{
printf("wsaaccept OK");
}
else
{
printf("wsaaccept error %d",WSAGetLastError());
}
perHandleData = (LP_PER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
perHandleData->socket = sClient;
CreateIoCompletionPort((HANDLE)sClient,hCompPort,(DWORD)perHandleData,0); //投递一次操作
//填充OVERLAPPED结构
perIoOperationData = (LP_PER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA)); ZeroMemory(&(perIoOperationData->ol),sizeof(OVERLAPPED));
perIoOperationData->bytesSend = 0;
perIoOperationData->bytesRecv = 0;
perIoOperationData->dataBuf.len = BUFF_SIZE;
perIoOperationData->dataBuf.buf = perIoOperationData->buffer;
DWORD flags = 0;
if( 0 == WSARecv(sClient,&(perIoOperationData->dataBuf),1,&(perIoOperationData->bytesRecv),&flags,(LPWSAOVERLAPPED)perIoOperationData,NULL))
{
printf("receive ok");
}
else
{
printf("receiv error %d",WSAGetLastError());
}
}
return 0;
}void CreateWorkThread(LPVOID hCompPort)
{
SYSTEM_INFO systemInfo;
GetSystemInfo(& systemInfo);
int i;
DWORD threadID;
HANDLE threadHandle;
for(i=0;i < systemInfo.dwNumberOfProcessors*2;i++)
{
threadHandle = CreateThread(NULL,0,ServerWorkerThread,hCompPort,0,&threadID);
CloseHandle(threadHandle);
}
}DWORD WINAPI ServerWorkerThread(LPVOID completionPortID)
{
HANDLE hCompPort = (HANDLE)completionPortID;
//处理消息
LP_PER_IO_OPERATION_DATA perIoOperationData;
LP_PER_HANDLE_DATA perHandleData; DWORD dwTransCount = 0;
while(true)//获取消息队列
{
printf("work thread");
if(GetQueuedCompletionStatus(hCompPort,&dwTransCount,(LPDWORD)&perHandleData,(LPOVERLAPPED *)&perIoOperationData,INFINITE) == 0)
{
printf(" GetQueuedCompletionStatus failed with error %d\n " , WSAGetLastError());
}
else
{
printf("get message ok transnum %d",dwTransCount);
}
switch(perIoOperationData->stClientToServer.iMessageType)
{
case REGISTER:
perIoOperationData->stClientToServer.message.loginmember.userName;
break;
case LOGIN:
printf("user name is %s",perIoOperationData->stClientToServer.message.loginmember.userName);
break;
case LOGOUT:
break;
}
printf("type is %d and userName is %s",perIoOperationData->stClientToServer.iMessageType,perIoOperationData->stClientToServer.message.loginmember.userName);
printf("receive io data %d",perIoOperationData->bytesRecv);
return 0;
}}
解决方案 »
- 怎么通过服务名获得服务进程句柄?服务与普通程序通信
- 使用ofstream 为什么输出int到文件会自动加千位符(1000 -> 1,000)
- 为什么程序关闭了,任务管理器中的线程还在运行?(vc++)
- 一个数学算法
- 如何用vc打开access97加密数据库
- 在工作线程的控制函数中设定定时器,没有反应
- 关于通过Project-->Add to project菜单来加入组件出现的问题,请高手帮我解决!!什么感谢!!
- 请问面的结构中有指尖那里怎样理解?
- 残念啊,高手指导CListbox关联CString变量的问题
- 用WNetEnumResource得到LAN中主机名和IP地址,请用VC实现之。分不够在加。
- 请问一下做Activex控件时,Add member variable对话框怎么调出来
- 判断文件名执行不同程序
一个奇怪的问题是,客户端WSASend 的 numberOfBytesSent 值为 0,yge
void CClientDlg::OnButton1()
{
// TODO: Add your control notification handler code here
//绑定端口
WSADATA wsaData; if(::WSAStartup(MAKEWORD(2,2),&wsaData) == 0)
{
//AfxMessageBox("INIT OK");
}
SOCKET sClient;
sClient = ::WSASocket(AF_INET,SOCK_STREAM,0,0,0,WSA_FLAG_OVERLAPPED);
if(sClient < 0)
{
AfxMessageBox("Make socket error");
}
//连接服务器
CString s;
SOCKADDR_IN saRemote;
saRemote.sin_family = AF_INET;
saRemote.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);
saRemote.sin_port = ::htons(SERVER_PORT);
if(::connect(sClient,(SOCKADDR *)&saRemote,sizeof(saRemote)) == 0)
{
//AfxMessageBox("connect ok"); }
else
{
s.Format("connect error%d",::WSAGetLastError());
AfxMessageBox(s);
} //发送用户名密码
stMessage clientToServerMessage;
clientToServerMessage.iMessageType = LOGIN;
char userName[10];
char password[10];
GetDlgItemText(IDC_EDIT1,userName,10);
GetDlgItemText(IDC_EDIT2,password,10); ::strncpy(clientToServerMessage.message.loginmember.userName,userName,10);
::strncpy(clientToServerMessage.message.loginmember.password,password,10);
LP_PER_IO_OPERATION_DATA pPerIoOperationData = (LP_PER_IO_OPERATION_DATA)::GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA)); ZeroMemory(&(pPerIoOperationData->ol),sizeof(pPerIoOperationData->ol));
pPerIoOperationData->stClientToServer = clientToServerMessage;
pPerIoOperationData->dataBuf.buf = pPerIoOperationData->buffer;
pPerIoOperationData->dataBuf.len = BUFF_SIZE;
DWORD dwFlags = 0;
DWORD numberOfBytesSent;
if(::WSASend(sClient,(LPWSABUF)&pPerIoOperationData->buffer,1,&numberOfBytesSent,dwFlags,(LPWSAOVERLAPPED)pPerIoOperationData,NULL) == SOCKET_ERROR)
{
s.Format("wsasend with error: %d",WSAGetLastError());
AfxMessageBox(s);
}
else
{
s.Format("wsasend data num is: %d",numberOfBytesSent);
AfxMessageBox(s);
}
}
填充时用的名令是 ZeroMemory(&pPerIoOperationData->ol,sizeof(OVERLAPPED));
基于MFC的
其中
pPerIoOperationData结构体为
typedef struct{
OVERLAPPED ol;
WSABUF dataBuf;
char buffer[BUFF_SIZE];
DWORD bytesSend;
DWORD bytesRecv;
stMessage stClientToServer;
}PER_IO_OPERATION_DATA,*LP_PER_IO_OPERATION_DATA;
typedef struct
{
SOCKET socket;
}PER_HANDLE_DATA,*LP_PER_HANDLE_DATA;
unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回)
因为我是 刚学VC的,到今天,这周是第三周开始,请你加我QQ 24645955 好吗,或者你留下QQ
或MSN 我加你,向你请教一下,我实在找不到哪里出问题了