完成端口实现echo tcp server
来源:互联网 发布:mac中safari下载视频 编辑:程序博客网 时间:2024/05/01 04:25
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 5150
#define DATA_BUFSIZE 8192
/*
*无论何时调用重叠操作函数时,总是会通过其lpOverlapped参数传递一个OVERLAPPEDPLUS结构
*(例如WSASend、 WSARecv等函数)。这就允许你为每一个重叠调用操作设置某些操作状态信息,
*当操作结束后,你可以通过GetQueuedCompletionStatus()函数获得你自定义结构的指针。
*/
typedef struct
{
OVERLAPPED Overlapped;
WSABUF dataBuf;
char buffer[DATA_BUFSIZE];
int OpCode;//传递操作码
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
#define OP_READ 0
#define OP_WRITE 1
#define OP_ACCEPT 2
//单句柄数据
typedef struct
{
SOCKET Socket;
}PER_HANDLE_DATA,* LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(void* completionPortID);
int main(int argc, char* argv[])
{
SOCKADDR_IN serverAddr;
SOCKET listenSocket;
SOCKET acceptSocket;
HANDLE completionPort;
WSADATA wsaData;
if(WSAStartup(0x0202, &wsaData) != 0)
{
printf("WSAStartup failed with error ");
return -1;
}
//建立完成端口
if((completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0)) == NULL)
{
printf( "CreateIoCompletionPort failed with error: %d ", GetLastError());
return -1;
}
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
DWORD threadID;
//创建工作者线程
for(int i = 0; i < systemInfo.dwNumberOfProcessors*2; i++)
{
HANDLE threadHandle;
if((threadHandle = CreateThread(NULL,0,ServerWorkerThread,completionPort,0,&threadID)) == NULL)
{
printf("CreateThread() failed with error %d ", GetLastError());
return -1;
}
CloseHandle(threadHandle);
}
if ((listenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d ", WSAGetLastError());
return -1;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(PORT);
if(bind(listenSocket,(sockaddr*)&serverAddr,sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d ", WSAGetLastError());
return -1;
}
if (listen(listenSocket, 10) == SOCKET_ERROR)
{
printf("listen() failed with error %d ", WSAGetLastError());
return -1;
}
for(;;)
{
if((acceptSocket = WSAAccept(listenSocket,NULL,NULL,NULL,0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d ", WSAGetLastError());
return -1;
}
LPPER_HANDLE_DATA perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
printf("socket number %d connected ",acceptSocket);
perHandleData->Socket = acceptSocket;
//新套接字句柄同完成端口关联到一起。
//通过完成键(CompletionKey)参数,将单句柄数据结构传递给完成端口。
if(CreateIoCompletionPort((HANDLE)acceptSocket,completionPort,(DWORD)perHandleData,
0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d ", GetLastError());
return -1 ;
}
//为重叠调用建立单I/O操作数据
LPPER_IO_OPERATION_DATA perIoData;
perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));
memset(&perIoData->Overlapped,0,sizeof(OVERLAPPED));
perIoData->dataBuf.len = DATA_BUFSIZE;
perIoData->dataBuf.buf = perIoData->buffer;
perIoData->OpCode = OP_READ; //读操作
/* 开始在接受套接字上处理I/O
* 使用重叠I/O机制,在新建的套接字上投递一个或多个异步
* WSARecv 或 WSASend请求。这些I/O请求完成后,工作者线程
* 会为I/O请求提供服务。
*/
DWORD recvBytes;
DWORD flags = 0;
WSARecv(acceptSocket,
&(perIoData->dataBuf),
1,
&recvBytes,
&flags,
&(perIoData->Overlapped),
NULL);
}
return 0;
}
DWORD WINAPI ServerWorkerThread(void* completionPortID)
{
HANDLE completionPort = (HANDLE)completionPortID;
DWORD bytesTransferred;
//LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA perIoData;
while(true)
{
if(GetQueuedCompletionStatus(completionPort,&bytesTransferred,
(LPDWORD)&perHandleData,(LPOVERLAPPED*)&perIoData,INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d ", GetLastError());
return 0;
}
if(bytesTransferred == 0)
{
printf("Closing socket %d ",perHandleData->Socket);
closesocket(perHandleData->Socket);
GlobalFree(perHandleData);
GlobalFree(perIoData);
continue;
}
switch (perIoData->OpCode)
{
case OP_ACCEPT:
break;
case OP_WRITE://写完成
{
// 为下一个重叠调用建立单I/O操作数据
memset(&perIoData->Overlapped,0,sizeof(OVERLAPPED));
perIoData->dataBuf.len = DATA_BUFSIZE;
perIoData->dataBuf.buf = perIoData->buffer;
perIoData->OpCode = OP_READ; //读操作
DWORD recvBytes;
DWORD flags = 0;
WSARecv(perHandleData->Socket,
&(perIoData->dataBuf),
1,
&recvBytes,
&flags,
&(perIoData->Overlapped),
NULL);
break;
}
case OP_READ://读完成
{
printf("recive socket %d :%s ",perHandleData->Socket,perIoData->buffer);
//为下一个重叠调用建立单I/O操作数据
//将接收到的数据echo 回去
memset(&perIoData->Overlapped,0,sizeof(OVERLAPPED));
perIoData->dataBuf.buf = perIoData->buffer;
perIoData->dataBuf.len = bytesTransferred;
perIoData->OpCode = OP_WRITE; //写操作
DWORD bytesSend;
DWORD flags = 0;
WSASend(perHandleData->Socket,&(perIoData->dataBuf),1,&bytesSend,
0,&(perIoData->Overlapped),0);
break;
}
}
}
}
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 5150
#define DATA_BUFSIZE 8192
/*
*无论何时调用重叠操作函数时,总是会通过其lpOverlapped参数传递一个OVERLAPPEDPLUS结构
*(例如WSASend、 WSARecv等函数)。这就允许你为每一个重叠调用操作设置某些操作状态信息,
*当操作结束后,你可以通过GetQueuedCompletionStatus()函数获得你自定义结构的指针。
*/
typedef struct
{
OVERLAPPED Overlapped;
WSABUF dataBuf;
char buffer[DATA_BUFSIZE];
int OpCode;//传递操作码
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
#define OP_READ 0
#define OP_WRITE 1
#define OP_ACCEPT 2
//单句柄数据
typedef struct
{
SOCKET Socket;
}PER_HANDLE_DATA,* LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(void* completionPortID);
int main(int argc, char* argv[])
{
SOCKADDR_IN serverAddr;
SOCKET listenSocket;
SOCKET acceptSocket;
HANDLE completionPort;
WSADATA wsaData;
if(WSAStartup(0x0202, &wsaData) != 0)
{
printf("WSAStartup failed with error ");
return -1;
}
//建立完成端口
if((completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0)) == NULL)
{
printf( "CreateIoCompletionPort failed with error: %d ", GetLastError());
return -1;
}
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
DWORD threadID;
//创建工作者线程
for(int i = 0; i < systemInfo.dwNumberOfProcessors*2; i++)
{
HANDLE threadHandle;
if((threadHandle = CreateThread(NULL,0,ServerWorkerThread,completionPort,0,&threadID)) == NULL)
{
printf("CreateThread() failed with error %d ", GetLastError());
return -1;
}
CloseHandle(threadHandle);
}
if ((listenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d ", WSAGetLastError());
return -1;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(PORT);
if(bind(listenSocket,(sockaddr*)&serverAddr,sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d ", WSAGetLastError());
return -1;
}
if (listen(listenSocket, 10) == SOCKET_ERROR)
{
printf("listen() failed with error %d ", WSAGetLastError());
return -1;
}
for(;;)
{
if((acceptSocket = WSAAccept(listenSocket,NULL,NULL,NULL,0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d ", WSAGetLastError());
return -1;
}
LPPER_HANDLE_DATA perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
printf("socket number %d connected ",acceptSocket);
perHandleData->Socket = acceptSocket;
//新套接字句柄同完成端口关联到一起。
//通过完成键(CompletionKey)参数,将单句柄数据结构传递给完成端口。
if(CreateIoCompletionPort((HANDLE)acceptSocket,completionPort,(DWORD)perHandleData,
0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d ", GetLastError());
return -1 ;
}
//为重叠调用建立单I/O操作数据
LPPER_IO_OPERATION_DATA perIoData;
perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));
memset(&perIoData->Overlapped,0,sizeof(OVERLAPPED));
perIoData->dataBuf.len = DATA_BUFSIZE;
perIoData->dataBuf.buf = perIoData->buffer;
perIoData->OpCode = OP_READ; //读操作
/* 开始在接受套接字上处理I/O
* 使用重叠I/O机制,在新建的套接字上投递一个或多个异步
* WSARecv 或 WSASend请求。这些I/O请求完成后,工作者线程
* 会为I/O请求提供服务。
*/
DWORD recvBytes;
DWORD flags = 0;
WSARecv(acceptSocket,
&(perIoData->dataBuf),
1,
&recvBytes,
&flags,
&(perIoData->Overlapped),
NULL);
}
return 0;
}
DWORD WINAPI ServerWorkerThread(void* completionPortID)
{
HANDLE completionPort = (HANDLE)completionPortID;
DWORD bytesTransferred;
//LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA perIoData;
while(true)
{
if(GetQueuedCompletionStatus(completionPort,&bytesTransferred,
(LPDWORD)&perHandleData,(LPOVERLAPPED*)&perIoData,INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d ", GetLastError());
return 0;
}
if(bytesTransferred == 0)
{
printf("Closing socket %d ",perHandleData->Socket);
closesocket(perHandleData->Socket);
GlobalFree(perHandleData);
GlobalFree(perIoData);
continue;
}
switch (perIoData->OpCode)
{
case OP_ACCEPT:
break;
case OP_WRITE://写完成
{
// 为下一个重叠调用建立单I/O操作数据
memset(&perIoData->Overlapped,0,sizeof(OVERLAPPED));
perIoData->dataBuf.len = DATA_BUFSIZE;
perIoData->dataBuf.buf = perIoData->buffer;
perIoData->OpCode = OP_READ; //读操作
DWORD recvBytes;
DWORD flags = 0;
WSARecv(perHandleData->Socket,
&(perIoData->dataBuf),
1,
&recvBytes,
&flags,
&(perIoData->Overlapped),
NULL);
break;
}
case OP_READ://读完成
{
printf("recive socket %d :%s ",perHandleData->Socket,perIoData->buffer);
//为下一个重叠调用建立单I/O操作数据
//将接收到的数据echo 回去
memset(&perIoData->Overlapped,0,sizeof(OVERLAPPED));
perIoData->dataBuf.buf = perIoData->buffer;
perIoData->dataBuf.len = bytesTransferred;
perIoData->OpCode = OP_WRITE; //写操作
DWORD bytesSend;
DWORD flags = 0;
WSASend(perHandleData->Socket,&(perIoData->dataBuf),1,&bytesSend,
0,&(perIoData->Overlapped),0);
break;
}
}
}
}
- 完成端口实现echo tcp server
- TCP Echo Server(select)
- ECHO TCP Server Client
- TCP echo server demo
- TCP实现ECHO程序
- libuv库TCP echo-server
- TCP 完成端口服务器构建
- TCP完成端口服务器构建
- select 实现 tcp echo 服务器
- lua + libuv 实现tcp echo
- 用完成端口写的echo server
- 用完成端口写的echo server
- 用完成端口写的echo server
- 用完成端口写的echo server
- 各种语言写的 tcp echo server
- 基于libuv的TCP echo-server
- Create TCP Echo Server using Libev
- TCP网络程序设计-完成端口之应用
- 犹太人经商25法则
- Statement (2)
- Windows API一日一练(44)wsprintf函数
- jsp语法之动作篇
- servlet读取web.xml中参数和页面转向方法
- 完成端口实现echo tcp server
- Apache conf中文说明
- How to Setup Apache With FastCGI And Ruby Bindings
- 中秋前夕
- 威金.绝望logo1_.exe 9sy.exe dll.dll rundl132.exe _desktop.ini
- 史上最完整的ruby,rails环境架设配置(Apache+fastcgi)
- 人生感悟
- 2007中秋节中/英文祝福短信
- 服务器公共组件实现 -- 状态机