C语言IOCP
C语言的IOCP example
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#include <stdio.h> #pragma comment(lib, "ws2_32.lib") #define Port 5000
#define Max_Buffer_Size 4096
#define Max_Threads 2 static GUID ax_guid = WSAID_ACCEPTEX;
static GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS; const char res_bufs[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nWelcome to Server."; LPFN_ACCEPTEX lpfn_AcceptEx;
LPFN_GETACCEPTEXSOCKADDRS lpfn_GetAcceptExSockAddrs; HANDLE iocp;
SOCKET listener; typedef struct
{
OVERLAPPED overlapped;
SOCKET accept;
WSABUF wsa_buf;
CHAR buf[Max_Buffer_Size];
DWORD bytes_send;
DWORD bytes_recv;
int action; } Pre_IO_Context, *LP_Pre_IO_Context; int init(void); DWORD WINAPI worker_thread(LPVOID iocp); int post_accept_ex();
int post_recv(Pre_IO_Context* io_ctx);
int post_send(Pre_IO_Context* io_ctx); int do_accept(HANDLE iocp, Pre_IO_Context* io_ctx);
int do_recv(Pre_IO_Context* io_ctx);
int do_send(Pre_IO_Context* io_ctx); int main(void)
{
int i;
DWORD thread_id;
HANDLE threads[Max_Threads];
LINGER linger;
SOCKADDR_IN inet_addr; int opt_val = 1;
int opt_len = sizeof(int); printf("Win IOCP"); if (-1 == init())
{
printf("init failed.");
return -1;
} if ((iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf("CreateIoCompletionPort Failed,err: %d\n", GetLastError());
return -1;
} for (i = 0; i < Max_Threads; i++)
{
if ((threads[i] = CreateThread(NULL, 0, worker_thread, iocp, 0, &thread_id)) == NULL)
{
printf("CreateThread() failed. error: %d\n", GetLastError());
CloseHandle(iocp);
WSACleanup();
return -1;
}
} if ((listener = WSASocketW(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed. error: %d\n", WSAGetLastError());
WSACleanup();
return -1;
} if (-1 == setsockopt(listener, SOL_SOCKET, SO_KEEPALIVE, (const void*)& opt_val, opt_len))
{
printf("setsockopt(SO_KEEPALIVE) failed.");
closesocket(listener);
WSACleanup();
CloseHandle(iocp);
return -1;
} // closesocket: return immediately and send RST
linger.l_onoff = 1;
linger.l_linger = 0;
if (-1 == setsockopt(listener, SOL_SOCKET, SO_LINGER, (char*)& linger, sizeof(linger)))
{
printf("setsockopt(SO_LINGER) failed.");
closesocket(listener);
WSACleanup();
CloseHandle(iocp);
return -1;
} // Windows only support SO_REUSEADDR
if (-1 == setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (const void*)& opt_val, opt_len))
{
printf("setsockopt(SO_REUSEADDR) failed.");
closesocket(listener);
WSACleanup();
CloseHandle(iocp);
return -1;
} if (INVALID_HANDLE_VALUE == CreateIoCompletionPort((HANDLE)listener, iocp, 0, 0))
{
printf("CreateIoCompletionPort(listener) failed.");
closesocket(listener);
WSACleanup();
CloseHandle(iocp);
return -1;
} printf("Associate socket with iocp. socket: %I64d, iocp: %p \n", listener, iocp); inet_addr.sin_family = AF_INET;
inet_addr.sin_addr.s_addr = htonl(INADDR_ANY);
inet_addr.sin_port = htons(Port);
if (SOCKET_ERROR == bind(listener, (PSOCKADDR)& inet_addr, sizeof(inet_addr)))
{
printf("bind() failed.");
closesocket(listener);
WSACleanup();
CloseHandle(iocp);
return -1;
} if (SOCKET_ERROR == listen(listener, SOMAXCONN))
{
printf("listen() failed.");
closesocket(listener);
WSACleanup();
CloseHandle(iocp);
return -1;
} printf("Listen on prot(%d).\n", Port); for (i = 0; i < Max_Threads; i++)
{
post_accept_ex();
} // MAXIMUM_WAIT_OBJECTS
WaitForMultipleObjects(Max_Threads, threads, FALSE, INFINITE); //PostQueuedCompletionStatus(iocp, 0, (DWORD)-1, NULL); printf("All threads exit."); return 0;
} int init(void)
{
SYSTEM_INFO sys_info;
WSADATA wsa_data; DWORD ret;
SOCKET s; GetSystemInfo(&sys_info); printf("System memery page size: %d \n", sys_info.dwPageSize);
printf("System cpus: %d \n", sys_info.dwNumberOfProcessors); if ((ret = WSAStartup(0x0202, &wsa_data)) != 0)
{
printf("WSAStartup() failed. error: %d\n", ret);
return -1;
} if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
{
printf("Require Windows Socket Version 2.2 Error!\n");
WSACleanup();
return -1;
} s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (s == -1) {
printf("socket() failed.");
return -1;
} if (-1 == WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ax_guid, sizeof(GUID),
&lpfn_AcceptEx, sizeof(LPFN_ACCEPTEX), &ret, NULL, NULL))
{
printf("WSAIoctl(LPFN_ACCEPTEX) failed.");
return -1;
} if (-1 == WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID),
&lpfn_GetAcceptExSockAddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS),
&ret, NULL, NULL))
{
printf("WSAIoctl(LPFN_GETACCEPTEXSOCKADDRS) failed.");
return -1;
} if (-1 == closesocket(s)) {
printf("closesocket() failed.");
return -1;
} return 0;
} DWORD WINAPI worker_thread(LPVOID lp_iocp)
{
DWORD bytes;
LP_Pre_IO_Context io_ctx; DWORD err_no = 0;
HANDLE iocp = (HANDLE)lp_iocp;
PULONG_PTR lp_completion_key = NULL; while (TRUE)
{
if (0 == GetQueuedCompletionStatus(iocp, &bytes, (PULONG_PTR)& lp_completion_key, (LPOVERLAPPED*)& io_ctx, INFINITE))
{
err_no = GetLastError(); if (err_no) { if (WAIT_TIMEOUT == err_no) continue; if (ERROR_NETNAME_DELETED == err_no || ERROR_OPERATION_ABORTED == err_no)
{
printf("The socket was closed. error: %d\n", err_no);
GlobalFree(io_ctx); continue;
} printf("GetQueuedCompletionStatus() failed. error: %d\n", err_no);
GlobalFree(io_ctx); return err_no;
}
} printf("GetQueuedCompletionStatus ---------------------------\n"); if (NULL == io_ctx)
{
printf("GetQueuedCompletionStatus() returned no operation");
continue;
} printf("IO_Context: %p \n", io_ctx);
printf("Bytes transferred: %d \n", bytes);
printf("IO_Context->Action: %d\n", io_ctx->action); if (0 == bytes && 0 != io_ctx->action)
{
printf("No bytes transferred for the action.");
GlobalFree(io_ctx);
continue;
} switch (io_ctx->action)
{
case 0:
post_accept_ex();
do_accept(iocp, io_ctx);
post_recv(io_ctx);
break; case 1:
do_recv(io_ctx);
post_send(io_ctx);
break; case 2:
do_send(io_ctx);
break; default:
printf("ERROR: No action match! \n");
break;
}
}
} int post_accept_ex()
{
LP_Pre_IO_Context io_ctx; printf("post_accept_ex. listner: %I64d\n", listener); if ((io_ctx = (LP_Pre_IO_Context)GlobalAlloc(GPTR, sizeof(Pre_IO_Context))) == NULL)
{
printf("GlobalAlloc() failed. error: %d\n", GetLastError());
return -1;
} ZeroMemory(&(io_ctx->overlapped), sizeof(OVERLAPPED));
io_ctx->bytes_recv = 0;
io_ctx->bytes_send = 0;
io_ctx->wsa_buf.len = Max_Buffer_Size;
io_ctx->wsa_buf.buf = io_ctx->buf;
io_ctx->action = 0; io_ctx->accept = WSASocketW(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == io_ctx->accept)
{
printf("WSASocketW() failed.\n");
return -1;
} if (0 == lpfn_AcceptEx(
listener, io_ctx->accept,
io_ctx->wsa_buf.buf,
//io_ctx->wsa_buf.len - (sizeof(SOCKADDR_IN) + 16) * 2,
0, sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16, &(io_ctx->bytes_recv),
&(io_ctx->overlapped)
)) {
if (WSA_IO_PENDING != WSAGetLastError())
{
printf("LPFN_ACCEPTEX() failed. last error: %d\n", WSAGetLastError());
return -1;
}
} printf("post_accept_ex. listner: %I64d, io_ctx: %p \n", listener, io_ctx); return 0;
} int do_accept(HANDLE iocp, Pre_IO_Context* io_ctx)
{
printf("do_accept. io_ctx: %p \n", io_ctx); SOCKADDR_IN* local_sock_addr = NULL;
SOCKADDR_IN* remote_sock_addr = NULL;
int addr_len = sizeof(SOCKADDR_IN); if (-1 == setsockopt(io_ctx->accept, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)& listener, sizeof(SOCKET)))
{
printf("setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed. error: %d\n", WSAGetLastError());
} lpfn_GetAcceptExSockAddrs(
io_ctx->wsa_buf.buf,
io_ctx->wsa_buf.len - ((addr_len + 16) * 2),
addr_len + 16,
addr_len + 16,
(SOCKADDR * *)& local_sock_addr, &addr_len,
(SOCKADDR * *)& remote_sock_addr, &addr_len
); printf("do_accept, client socket: %I64d \n", io_ctx->accept); if (NULL == CreateIoCompletionPort((HANDLE)io_ctx->accept, iocp, 0, 0))
{
printf("CreateIoCompletionPort() failed. error: %d\n", GetLastError());
return -1;
} return 0;
} int post_recv(Pre_IO_Context* io_ctx)
{
printf("post_recv. io_ctx: %p \n", io_ctx); DWORD flags = 0;
DWORD bytes = 0;
DWORD err_no;
int ret; ZeroMemory(&(io_ctx->overlapped), sizeof(OVERLAPPED));
io_ctx->bytes_recv = 0;
io_ctx->bytes_send = 0;
io_ctx->wsa_buf.len = Max_Buffer_Size;
io_ctx->wsa_buf.buf = io_ctx->buf;
io_ctx->action = 1; ret = WSARecv(io_ctx->accept, &(io_ctx->wsa_buf), 1, &bytes, &flags, &(io_ctx->overlapped), NULL); err_no = WSAGetLastError();
if (-1 == ret && WSA_IO_PENDING != err_no)
{
if (err_no == WSAEWOULDBLOCK) printf("WSARecv() not ready"); printf("WSARecv() faild. client socket: %I64d, error: %d\n", io_ctx->accept, err_no); return -1;
} return 0;
} int do_recv(Pre_IO_Context* io_ctx)
{
printf("do_recv. io_ctx: %p \n", io_ctx);
printf("do_recv: recv data:\n %s \n", io_ctx->wsa_buf.buf); ZeroMemory(&(io_ctx->overlapped), sizeof(OVERLAPPED));
io_ctx->bytes_recv = 0;
io_ctx->bytes_send = 0;
io_ctx->wsa_buf.len = Max_Buffer_Size;
io_ctx->wsa_buf.buf = io_ctx->buf;
io_ctx->action = 10; return 0;
} int post_send(Pre_IO_Context* io_ctx)
{
printf("post_send. io_ctx: %p \n", io_ctx); DWORD flags = 0;
DWORD bytes = 0;
DWORD err_no;
int ret; io_ctx->wsa_buf.buf = &res_bufs;
io_ctx->wsa_buf.len = sizeof(res_bufs) - 1; //io_ctx->overlapped.hEvent = WSACreateEvent();
io_ctx->action = 2; ret = WSASend(io_ctx->accept, &(io_ctx->wsa_buf), 1, &bytes, 0, &(io_ctx->overlapped), NULL);
err_no = WSAGetLastError(); if (-1 == ret && err_no != WSA_IO_PENDING)
{
printf("WSASend() faild. error: %d\n", err_no); //WSAResetEvent(io_ctx->overlapped.hEvent);
return -1;
} if (err_no == WSA_IO_PENDING)
{
printf("WSASend() posted. bytest: %d err: %d\n", bytes, err_no);
} printf("WSASend send bytest: %d \n", bytes); /*
WSAWaitForMultipleEvents(1, &io_ctx->overlapped.hEvent, TRUE, INFINITE, TRUE);
printf("WSAWaitForMultipleEvents() failed. err: %d\n", WSAGetLastError()); WSAGetOverlappedResult(io_ctx->accept, &io_ctx->overlapped, &io_ctx->bytes_send, FALSE, &flags);
printf("WSAGetOverlappedResult() send bytes: %d\n", io_ctx->bytes_send); WSAResetEvent(io_ctx->overlapped.hEvent);
printf("WSAResetEvent() err: %d\n", WSAGetLastError());
*/ return 0;
} int do_send(Pre_IO_Context* io_ctx)
{
printf("do_send. io_ctx: %p \n", io_ctx); shutdown(io_ctx->accept, SD_BOTH);
GlobalFree(io_ctx); return 0;
}
仅记录一个简单的示例,没有严谨的处理。同时谅解一下代码风格。
C语言IOCP的更多相关文章
- 咏南IOCP REST中间件
咏南IOCP REST中间件 让DELPHI7也能编写REST服务. 使用IOCP通信+UNIDAC数据库引擎. 客户端跨开发语言调用.
- 咏南IOCP中间件支持海量并发方案(集群)
咏南IOCP中间件支持海量并发方案(集群) 支持D7~XE10.1.1开发 支持负载均衡,自动故障转移 可以在不停机的状态下,根据负载情况灵活增加中间件机器 中间件使用IOCP通信,单中间件支持并发数 ...
- IOCP 浅析
http://www.ibm.com/developerworks/cn/java/j-lo-iocp/ https://msdn.microsoft.com/en-us/library/window ...
- <转>Go语言TCP Socket编程
授权转载: Tony Bai 原文连接: https://tonybai.com/2015/11/17/tcp-programming-in-golang/ Golang的主要 设计目标之一就是面向大 ...
- Go语言学习之9 网络协议TCP、Redis与聊天室
主要内容 1. Tcp编程2. redis使用 1. Tcp编程 (1)简介 Golang是谷歌设计开发的语言,在Golang的设计之初就把高并发的性能作为Golang的主要特性之一,也是 ...
- IOCP编程原理(转)
在我的博客之前写了很多关于IOCP的“行云流水”似的看了让人发狂的文章,尤其是几篇关于 IOCP加线程池文章,更是让一些功力不够深厚的初学IOCP者,有种吐血的感觉.为了让大家能够立刻提升内力修为,并 ...
- IOCP编程小结(上)
前段时间接手了一个网络游戏前端连接服务器的开发工作,由于服务器需要在windows平台上部署,并且需要处理大量的客户端连接,因此采用IOCP来做为服务器端的编程模型就成了不二选择.虽然我对服务器开发并 ...
- IOCP编程小结(中)
上一篇主要谈了一些基本理念,本篇将谈谈我个人总结的一些IOCP编程技巧. 网络游戏前端服务器的需求和设计 首先介绍一下这个服务器的技术背景.在分布式网络游戏服务器中,前端连接服务器是一种很常见的设计. ...
- IOCP编程之基本原理
在我的博客之前写了很多关于IOCP的“行云流水”似的看了让人发狂的文章,尤其是几篇关于IOCP加线程池文章,更是让一些功力不够深厚的初学IOCP者,有种吐血的感觉.为了让大家能够立刻提升内力修为,并且 ...
随机推荐
- kill 与 killall和过滤后杀掉
1.绝杀 kill -9 PID 杀掉单一进程 例如:kill -9 pid号 同意的 kill -s SIGKILL 这个强大和危险的命令迫使进程在运行时突然终止,进程在结束后不能自我清 ...
- JavaScript_AMD规范
JavaScript_AMD规范 一.总结 一句话总结: Asynchronous Module Definition:AMD是"Asynchronous Module Definition ...
- 深度学习基础——Epoch、Iteration、Batchsize
原文地址:https://www.cnblogs.com/Johnny-z6951/p/11201081.html 梯度下降是一个在机器学习中用于寻找较佳结果(曲线的最小值)的迭代优化算法.梯度的含义 ...
- SVN 清理失败解决方案
SVN有时因各种不明原因导致清理失败,可以采取如下解决办法进行处理: 方法一: 删除根目录下隐藏文件夹“.svn” 然后在根目录文件夹 外面的空白处 检出.比如你项目文件夹名为“D:/source” ...
- [mysql]多个字段确定唯一性-联合唯一索引
一.联合唯一索引项目中需要用到联合唯一索引: 例如:有以下需求:每个人每一天只有可能产生一条记录:处了程序约定之外,数据库本身也可以设定: 例如:t_aa 表中有aa,bb两个字段,如果不希望有2条一 ...
- WPF VLC客户端和SDK的简单应用
VLC_SDK编程指南 VLC 是一款自由.开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及 DVD.音频 CD.VCD 及各类流媒体协议.它可以支持目前市面上大多数的视频解码,除了Rea ...
- nmon(linux监视)
nmon –f –t –r test –s 10 –c 60 即为10分钟 上面命令的含义是:-f :按标准格式输出文件名称:<hostname>_YYYYMMDD_HHMM.nmon-t ...
- 在DBGrid中,按ctrl+Delete不让删除,怎么实现
DBGrid的Options中的dgConfirmDelete改为:False;在DBGrid所连接的DataSet的BeforeDelete事件中写:Abort; ^_^
- etcd单节点安装
本篇安装单个etcd,然后进行扩容etcd节点至2个,环境配置如果做了的话就跳过 实验架构 test1: 192.168.0.91 etcd test2: 192.168.0.92 无 test3: ...
- C#学习笔记三(委托·lambda表达式和事件,字符串和正则表达式,集合,特殊的集合)
委托和事件的区别 序号 区别 委托 事件 1 是否可以使用=来赋值 是 否 2 是否可以在类外部进行调用 是 否 3 是否是一个类型 是 否,事件修饰的是一个对象 public delegate vo ...