// iocpServ.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
/**
* iocpSerc.c
*/#include <stdio.h>
#include <windows.h>
#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")#define TCP_PORT 5150
#define DATA_BUFSIZE 8192typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuffer;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesRecv;
DWORD BytesSend;
}PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA; typedef struct
{
SOCKET Socket;
}PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID);
void main(void)
{
WSADATA wsaData;
SOCKADDR_IN InternetAddr;
SOCKET ListenSocket;
SOCKET AcceptSocket;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA perIoData;
HANDLE CompletionPort;
// HANDLE hThread;
DWORD RecvBytes;
DWORD ThreadId;
SYSTEM_INFO SystemInfo;
DWORD Ret;
DWORD Flags;
int i;
// 加载winsock2.2
Ret = WSAStartup(0x0202, &wsaData);
// Ret = WSAStartup(MAKEWORD(2,2), &wsaData)
if(0 != Ret)
{
printf("WSAStartup failed with error%d\n", Ret);
return;
}
// 创建一个完成端口
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if(NULL == CompletionPort)
{
printf("CreateIoCompletionPort() failed with error%d\n", GetLastError());
return;
}
// 查看系统处理器个数
GetSystemInfo(&SystemInfo);
// 根据系统现有的处理器创建合理的线程数
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE hThread;
// 创建一个线程,把完成端口传递给它
hThread = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadId);
if(NULL == hThread)
{
printf("CreateThread() failed with error%d\n", GetLastError());
return;
}
// 关闭线程
CloseHandle(hThread);
}
// 创建一个套接字
ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == ListenSocket)
{
printf("WSASocket() failed with error%d\n", WSAGetLastError());
return;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(TCP_PORT);
//绑定套接字
if(SOCKET_ERROR == bind(ListenSocket, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)))
{
printf("bind() faile with error%d\n", WSAGetLastError());
return;
}
//监听套接字
if(SOCKET_ERROR == listen(ListenSocket, 5))
{
printf("listen() failed with error%d\n", WSAGetLastError());
return;
}
// 接受socket,并把它与完成端口关联
while(TRUE)
{
AcceptSocket = WSAAccept(ListenSocket, NULL, NULL, NULL, 0);
if(SOCKET_ERROR == AcceptSocket)
{
printf("WSAAccept() failed with error%d\n", WSAGetLastError());
return;
}
perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(LPPER_HANDLE_DATA));
if(NULL == perHandleData)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
} printf("Socket number %d connect\n", AcceptSocket);
perHandleData->Socket = AcceptSocket;
if(NULL == CreateIoCompletionPort((HANDLE)AcceptSocket, CompletionPort, (DWORD)perHandleData, 0))
{
printf("CreateIoCompletionPort() failed with error %d\n", GetLastError());
return;
}
perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(LPPER_IO_OPERATION_DATA));
if(NULL == perIoData)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
ZeroMemory(&(perIoData->Overlapped), sizeof(OVERLAPPED));
perIoData->BytesRecv = 0;
perIoData->BytesSend = 0;
perIoData->DataBuffer.len = DATA_BUFSIZE;
perIoData->DataBuffer.buf = perIoData->Buffer;
Flags = 0;
if(SOCKET_ERROR == WSARecv(AcceptSocket, &(perIoData->DataBuffer), 1, &(RecvBytes), &Flags, &(perIoData->Overlapped), NULL))
{
if(WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
}
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE)CompletionPortID;
DWORD BytesTransferred;
LPOVERLAPPED Overlapped;
LPPER_IO_OPERATION_DATA perIoData;
LPPER_HANDLE_DATA perHandleData;
DWORD SendBytes, RecyBytes;
DWORD Flags;
while(TRUE)
{
if(GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&perHandleData, (LPOVERLAPPED *)&perIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus() failed with error %d\n", GetLastError());
return 0;
} if(0 == BytesTransferred)
{
printf("Closing socket %d\n", perHandleData->Socket);
if(SOCKET_ERROR == closesocket(perHandleData->Socket))
{
printf("closesocket() failed with error %d\n"), WSAGetLastError();
return 0;
}
GlobalFree(perHandleData);
GlobalFree(perIoData);
continue;
}
if(0 == perIoData->BytesRecv)
{
perIoData->BytesRecv = BytesTransferred;
perIoData->BytesSend = 0;
printf("BytesRecv:%s\n", perIoData->BytesRecv);
}
else
{
perIoData->BytesSend += BytesTransferred;
printf("BytesSend:%s\n", perIoData->BytesSend);
}
if(perIoData->BytesRecv > perIoData->BytesSend)
{
ZeroMemory(&(perIoData->Overlapped), sizeof(OVERLAPPED));
perIoData->DataBuffer.buf = perIoData->Buffer + perIoData->BytesSend;
perIoData->DataBuffer.len = perIoData->BytesRecv - perIoData->BytesSend;
if(SOCKET_ERROR == WSASend(perHandleData->Socket, &(perIoData->DataBuffer), 1,
&SendBytes, 0, &(perIoData->Overlapped), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
}
}
else
{
perIoData->BytesRecv = 0;
Flags = 0;
ZeroMemory(&(perIoData->Overlapped), sizeof(OVERLAPPED));
perIoData->DataBuffer.len = DATA_BUFSIZE;
perIoData->DataBuffer.buf = perIoData->Buffer; if(SOCKET_ERROR == WSARecv(perHandleData->Socket, &(perIoData->DataBuffer), 1,
&RecyBytes, &Flags, &(perIoData->Overlapped), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 0;
}
}
}
}
}
在上述红色处报有问题:
DataBufferf - buf 0x00040003 <错误的指针> char *
BytesRecv CXX0030: 错误: 无法计算表达式的值
BytesSend CXX0030: 错误: 无法计算表达式的值
解决方案 »
- 利用WIN API中CreateFile函数和GetLastError获得计算机获取计算机可用串口!
- 都说VC区没人气,那就散点分聚人气
- VC中如何让MSChart绘制的图形紧凑一些?
- 怎么在OpenGL中是实现现实场景图片与虚拟场景图象的融合?
- 问一个我非常困惑 懂的人觉得非常简单的小问题? 希望讲的通俗易懂~~~..........
- 求RSA加密算法的"C"或则"VC"的源代码(分不是问题)
- 一个有意思的问题!
- 请求赐教!
- 如何实现当对话框弹出的时候,用户点击其他区域都无效(包括桌面的开始菜单),只能点击对话框的确定按钮。
- 急:VC在不同操作系统下调用系统对话框的字体问题
- 已经编好的控制台程序与MFC界面结合的问题
- 关于tree contrl节点的收缩和展开的问提
改成如下:
perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
但在接下来又发生了个错误:
iocpServ.exe 中的 0x10227c2f (msvcr80d.dll) 处未处理的异常: 0xC0000005: 读取位置 0x00000009 时发生访问冲突
perIoData CXX0017: 错误: 没有找到符号“perIoData”,
错误指向output.c文件。碰到内存、指针错误不知从何入手,有谁能提供点资料学习下吗?谢谢了!
msvcr80d.dll!_output_l(_iobuf * stream=0x10310bf0, const char * format=0x0041684c, localeinfo_struct * plocinfo=0x00000000, char * argptr=0x0061fe88) 行1646 + 0x1f 字节msvcr80d.dll!printf(const char * format=0x00416840, ...) 行63 + 0x18 字节 iocpServ.exe!ServerWorkerThread(void * CompletionPortID=0x00000fc0) 行201 + 0x17 字节
http://blog.csdn.net/jasonM2008/archive/2009/08/13/4441514.aspx
printf("BytesRecv:%s\n", perIoData->BytesRecv);
printf("BytesRecv:%d\n", perIoData->BytesRecv);
借用学习