Windows Socket I/O模型之 WSAEventSelect模式
来源:互联网 发布:fc2破解版域名v7v6 编辑:程序博客网 时间:2024/06/05 16:17
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include "public.h"
- #include "resolve.h"
- typedef SINGLE_LIST_HEADER BuffHeader;
- typedef SINGLE_LIST BuffObj;
- typedef SINGLE_LIST_HEADER TheadObjHeader;
- typedef SINGLE_LIST ThreadObj;
- typedef DOUBLE_LIST_HEADER SockObjHeader;
- typedef DOUBLE_LIST SockObj;
- typedef struct _SOCKET_OBJ
- {
- SOCKET s; // Socket handle
- HANDLE event; // Event handle
- int listening; // Socket is a listening socket (TCP)
- int closing; // Indicates whether the connection is closing
- SOCKADDR_STORAGE addr; // Used for client's remote address
- int addrlen; // Length of the address
- BuffHeader buff;
- DOUBLE_LIST entry;
- } SOCKET_OBJ;
- typedef struct _THREAD_OBJ
- {
- SockObjHeader sockHeader;
- HANDLE Event; // Used to signal new clients assigned
- // to this thread
- HANDLE Thread;
- HANDLE Handles[MAXIMUM_WAIT_OBJECTS]; // Array of socket's event handles
- CRITICAL_SECTION ThreadCritSec; // Protect access to SOCKET_OBJ lists
- ThreadObj entry; // Next thread object in list
- } THREAD_OBJ;
- TheadObjHeader theadObjHeader;
- SOCKET_OBJ* GetSocketObj(SOCKET s, int listening) {
- SOCKET_OBJ *sockobj = NULL;
- sockobj = (SOCKET_OBJ*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_OBJ));
- if (sockobj == NULL) {
- fprintf(stderr, "HeapAlloc failed./n");
- ExitProcess(-1);
- }
- sockobj->s = s;
- sockobj->listening = listening;
- sockobj->addrlen = sizeof(sockobj->addr);
- sockobj->event = WSACreateEvent();
- if (sockobj->event == NULL)
- {
- fprintf(stderr, "GetSocketObj: WSACreateEvent failed: %d/n", WSAGetLastError());
- ExitProcess(-1);
- }
- InitializeCriticalSection(&sockobj->buff.SendRecvQueueCritSec);
- return sockobj;
- }
- THREAD_OBJ *GetThreadObj() {
- THREAD_OBJ *thread = NULL;
- thread = (THREAD_OBJ*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THREAD_OBJ));
- if (thread == NULL) {
- fprintf(stderr, "HeapAllco failed./n");
- ExitProcess(-1);
- }
- thread->Event = WSACreateEvent();
- if (thread->Event == NULL) {
- fprintf(stderr, "WSACreateEvent failed./n");
- ExitProcess(-1);
- }
- thread->Handles[0] = thread->Event;
- InitializeCriticalSection(&thread->ThreadCritSec);
- InitializeDoubleHead(&thread->sockHeader);
- return thread;
- }
- int InsertSocketObj(THREAD_OBJ *thread, SOCKET_OBJ *sockobj) {
- int ret;
- EnterCriticalSection(&thread->ThreadCritSec);
- if (thread->sockHeader.count < MAXIMUM_WAIT_OBJECTS - 1) {
- EnqueueDoubleListHead(&(thread->sockHeader), &(sockobj->entry));
- thread->Handles[thread->sockHeader.count] = sockobj->event;
- ret = NO_ERROR;
- } else {
- ret = SOCKET_ERROR;
- }
- LeaveCriticalSection(&thread->ThreadCritSec);
- return ret;
- }
- SOCKET_OBJ *FindSocketObj(THREAD_OBJ *thread, int index) {
- SOCKET_OBJ *sockobj = NULL;
- int i;
- EnterCriticalSection(&thread->ThreadCritSec);
- SockObj *sptr = (SockObj *)GotoNextDoubleList(&thread->sockHeader, &(thread->sockHeader.head));
- for (i = 0; i < index; ++i) {
- if (sptr == NULL)
- {
- fprintf(stderr, "FindSocketobj failed./n");
- ExitProcess(-1);
- }
- sptr = (SockObj *)GotoNextDoubleList(&thread->sockHeader, sptr);
- }
- sockobj = (SOCKET_OBJ *)container_of(SOCKET_OBJ, entry, sptr);
- LeaveCriticalSection(&thread->ThreadCritSec);
- return sockobj;
- }
- void RemoveSocketObj(THREAD_OBJ *thread, SOCKET_OBJ *sock) {
- EnterCriticalSection(&thread->ThreadCritSec);
- RemoveDoubleList(&thread->sockHeader, &sock->entry);
- WSASetEvent(thread->Event);
- LeaveCriticalSection(&thread->ThreadCritSec);
- }
- void FreeSocketObj(SOCKET_OBJ *obj) {
- BuffObj *ptr = NULL;
- BUFFER_OBJ *blk = NULL;
- while (true) {
- ptr = DequeueSingleList(&obj->buff);
- if (ptr == NULL)
- break;
- blk = (BUFFER_OBJ *)container_of(BUFFER_OBJ, next, ptr);
- FreeBufferObj(blk);
- }
- WSACloseEvent(obj->event);
- if (obj->s != INVALID_SOCKET) {
- closesocket(obj->s);
- }
- HeapFree(GetProcessHeap(), 0, obj);
- }
- void RenumberThreadArray(THREAD_OBJ *thread) {
- EnterCriticalSection(&thread->ThreadCritSec);
- SOCKET_OBJ *obj = NULL;
- int i = 0;
- SockObj *sptr = NULL;
- sptr = (SockObj *)GotoNextDoubleList(&thread->sockHeader, &(thread->sockHeader.head));
- while (sptr) {
- obj = (SOCKET_OBJ *)container_of(SOCKET_OBJ, entry, sptr);
- thread->Handles[++i] = obj->event;
- sptr = (SockObj *)GotoNextDoubleList(&thread->sockHeader, sptr);
- }
- LeaveCriticalSection(&thread->ThreadCritSec);
- }
- int ReceivePendingData(SOCKET_OBJ *sockobj) {
- BUFFER_OBJ *buffobj=NULL;
- int rc,
- ret;
- // Get a buffer to receive the data
- buffobj = GetBufferObj(gBufferSize);
- ret = 0;
- if (gProtocol == IPPROTO_TCP)
- {
- rc = recv(sockobj->s, buffobj->buf, buffobj->buflen, 0);
- } else {
- fprintf(stderr, "Tcp failed./n");
- ExitProcess(-1);
- }
- if (rc == SOCKET_ERROR) {
- fprintf(stderr, "recv failed./n");
- ExitProcess(-1);
- } else if (rc == 0) {
- FreeBufferObj(buffobj);
- sockobj->closing = TRUE;
- if (sockobj->buff.head == NULL)
- {
- // If no sends are pending, close the socket for good
- closesocket(sockobj->s);
- sockobj->s = INVALID_SOCKET;
- ret = -1;
- }
- else
- {
- ret = 0;
- }
- } else {
- buffobj->buflen = rc;
- EnqueueSingleList(&sockobj->buff, &buffobj->next);
- ret = 1;
- }
- return ret;
- }
- int SendPendingData(SOCKET_OBJ *sock) {
- BUFFER_OBJ *bufobj = NULL;
- BuffObj *entry = NULL;
- int nleft = 0,
- idx = 0,
- ret = 0,
- rc = 0;
- while (entry = DequeueSingleList(&sock->buff)) {
- bufobj = (BUFFER_OBJ *)container_of(BUFFER_OBJ, next, entry);
- if (gProtocol == IPPROTO_TCP) {
- nleft = bufobj->buflen;
- idx = 0;
- while (nleft > 0) {
- rc = send(sock->s, &(bufobj->buf[idx]), nleft, 0);
- if (rc == SOCKET_ERROR) {
- ExitProcess(-1);
- } else {
- idx += rc;
- nleft -= rc;
- }
- }
- printf("send %d./n", bufobj->buflen);
- FreeBufferObj(bufobj);
- } else {
- ExitProcess(-1);
- }
- }
- if ((sock->buff.head == NULL) && (sock->closing == TRUE)) {
- closesocket(sock->s);
- sock->s = INVALID_SOCKET;
- ret = -1;
- printf("Closing Connection./n");
- }
- return ret;
- }
- int HandleIo(THREAD_OBJ *thread, SOCKET_OBJ *sock) {
- WSANETWORKEVENTS nevents;
- int rc;
- // Enumerate the events
- rc = WSAEnumNetworkEvents(sock->s, sock->event, &nevents);
- if (rc == SOCKET_ERROR)
- {
- fprintf(stderr, "HandleIo: WSAEnumNetworkEvents failed: %d/n", WSAGetLastError());
- return SOCKET_ERROR;
- }
- if (nevents.lNetworkEvents & FD_READ) {
- if (nevents.iErrorCode[FD_READ_BIT] == 0) {
- rc = ReceivePendingData(sock);
- if (rc == -1)
- {
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- rc = SendPendingData(sock);
- if (rc == -1)
- {
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- } else {
- fprintf(stderr, "HandleIo: FD_READ error %d/n", nevents.iErrorCode[FD_READ_BIT]);
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- }
- if (nevents.lNetworkEvents & FD_WRITE) {
- if (nevents.iErrorCode[FD_WRITE_BIT] == 0)
- {
- rc = SendPendingData(sock);
- if (rc == -1)
- {
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- }
- else
- {
- fprintf(stderr, "HandleIo: FD_WRITE error %d/n", nevents.iErrorCode[FD_WRITE_BIT]);
- return SOCKET_ERROR;
- }
- }
- if (nevents.lNetworkEvents & FD_CLOSE) {
- if (nevents.iErrorCode[FD_CLOSE_BIT] == 0)
- {
- // Socket has been indicated as closing so make sure all the data
- // has been read
- printf("close./n");
- while (1)
- {
- rc = ReceivePendingData(sock);
- if (rc == -1)
- {
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- else if (rc != 0)
- {
- continue;
- }
- else
- {
- break;
- }
- }
- // See if there is any data pending, if so try to send it
- rc = SendPendingData(sock);
- if (rc == -1)
- {
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- }
- else
- {
- fprintf(stderr, "HandleIo: FD_CLOSE error %d/n", nevents.iErrorCode[FD_CLOSE_BIT]);
- RemoveSocketObj(thread, sock);
- FreeSocketObj(sock);
- return SOCKET_ERROR;
- }
- }
- return NO_ERROR;
- }
- DWORD WINAPI ChildThread(LPVOID lpParam) {
- THREAD_OBJ *thread=NULL;
- SOCKET_OBJ *sptr=NULL,
- *sockobj=NULL;
- int index,
- rc,
- i;
- thread = (THREAD_OBJ *)lpParam;
- while (true) {
- rc = WaitForMultipleObjects(thread->sockHeader.count + 1, thread->Handles, FALSE, INFINITE);
- if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
- {
- fprintf(stderr, "ChildThread: WaitForMultipleObjects failed: %d/n", GetLastError());
- break;
- } else {
- for(i = 0; i < thread->sockHeader.count + 1; i++) {
- rc = WaitForSingleObject(thread->Handles[i], 0);
- if (rc == WAIT_FAILED)
- {
- fprintf(stderr, "ChildThread: WaitForSingleObject failed: %d/n", GetLastError());
- ExitThread(-1);
- }
- else if (rc == WAIT_TIMEOUT)
- {
- // This event isn't signaled, continue to the next one
- continue;
- }
- index = i;
- if (index == 0)
- {
- // If index 0 is signaled then rebuild the array of event
- // handles to wait on
- WSAResetEvent(thread->Handles[index]);
- RenumberThreadArray(thread);
- i = 1;
- } else {
- sockobj = FindSocketObj(thread, index-1);
- if (sockobj != NULL)
- {
- if (HandleIo(thread, sockobj) == SOCKET_ERROR)
- {
- RenumberThreadArray(thread);
- }
- }
- else
- {
- printf("Unable to find socket object!/n");
- }
- }
- }
- }
- }
- }
- void AssignToFreeThread(SOCKET_OBJ *sock) {
- ThreadObj *threadobj = NULL;
- THREAD_OBJ *thread = NULL;
- threadobj = (ThreadObj *)GotoNextSingleList(&theadObjHeader, theadObjHeader.head);
- while (threadobj) {
- thread = (THREAD_OBJ *)container_of(THREAD_OBJ, entry, threadobj);
- if (InsertSocketObj(thread, sock) != SOCKET_ERROR) {
- break;
- }
- threadobj = (ThreadObj *)GotoNextSingleList(&theadObjHeader, threadobj);
- }
- if (threadobj == NULL) {
- thread = GetThreadObj();
- thread->Thread = CreateThread(NULL, 0, ChildThread, (LPVOID)thread, 0, NULL);
- if (thread->Thread == NULL)
- {
- fprintf(stderr, "AssignToFreeThread: CreateThread failed: %d/n", GetLastError());
- ExitProcess(-1);
- }
- InsertSocketObj(thread, sock);
- EnqueueSingleList(&theadObjHeader, &thread->entry);
- }
- WSASetEvent(thread->Event);
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- WSADATA wsd;
- struct addrinfo *res=NULL,
- *ptr=NULL;
- THREAD_OBJ *thread=NULL;
- SOCKET_OBJ *sockobj=NULL,
- *newsock=NULL;
- int index,
- rc;
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
- {
- fprintf(stderr, "unable to load Winsock!/n");
- return -1;
- }
- res = ResolveAddress(gSrvAddr, gPort, gAddressFamily, gSocketType, gProtocol);
- if (res == NULL)
- {
- fprintf(stderr, "ResolveAddress failed to return any addresses!/n");
- return -1;
- }
- thread = GetThreadObj();
- InitializeCriticalSection(&theadObjHeader.SendRecvQueueCritSec);
- theadObjHeader.head = theadObjHeader.tail = NULL;
- ptr = res;
- while (ptr) {
- sockobj = GetSocketObj(INVALID_SOCKET, (gProtocol == IPPROTO_TCP) ? TRUE : FALSE);
- sockobj->s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
- if (sockobj->s == INVALID_SOCKET) {
- fprintf(stderr, "create socket failed./n");
- ExitProcess(-1);
- }
- InsertSocketObj(thread, sockobj);
- rc = bind(sockobj->s, ptr->ai_addr, ptr->ai_addrlen);
- if (rc == SOCKET_ERROR)
- {
- fprintf(stderr, "bind failed: %d/n", WSAGetLastError());
- return -1;
- }
- if (gProtocol == IPPROTO_TCP) {
- rc = listen(sockobj->s, 200);
- if (rc == SOCKET_ERROR) {
- fprintf(stderr, "listen failed./n");
- ExitProcess(-1);
- }
- rc = WSAEventSelect(sockobj->s, sockobj->event, FD_ACCEPT | FD_CLOSE);
- if (rc == SOCKET_ERROR) {
- fprintf(stderr, "WSAEventSelect failed: %d/n", WSAGetLastError());
- ExitProcess(-1);
- }
- }
- ptr = ptr->ai_next;
- }
- freeaddrinfo(res);
- while (true) {
- rc = WaitForMultipleObjects(thread->sockHeader.count + 1, thread->Handles, FALSE, 5000);
- if (rc == WAIT_FAILED) {
- fprintf(stderr, "WaitForMultipleObjects failed:%d/n", WSAGetLastError());
- break;
- } else if (rc == WAIT_TIMEOUT) {
- continue;
- } else {
- index = rc - WAIT_OBJECT_0;
- sockobj = FindSocketObj(thread, index - 1);
- if (gProtocol == IPPROTO_TCP) {
- SOCKADDR_STORAGE sa;
- WSANETWORKEVENTS ne;
- SOCKET sc;
- int salen;
- rc = WSAEnumNetworkEvents(sockobj->s, thread->Handles[index], &ne);
- if (rc == SOCKET_ERROR) {
- fprintf(stderr, "WSAEnumNetworkEvents failed./n");
- break;
- }
- while (true) {
- sc = INVALID_SOCKET;
- salen = sizeof(sa);
- sc = accept(sockobj->s, (SOCKADDR *)&sa, &salen);
- if ((sc == INVALID_SOCKET) && (WSAGetLastError() != WSAEWOULDBLOCK)) {
- fprintf(stderr, "accept failed./n");
- break;
- } else if (sc == INVALID_SOCKET){
- continue;
- } else {
- newsock = GetSocketObj(INVALID_SOCKET, FALSE);
- memcpy(&newsock->addr, &sa, salen);
- newsock->addrlen = salen;
- newsock->s = sc;
- rc = WSAEventSelect(newsock->s, newsock->event, FD_READ | FD_WRITE | FD_CLOSE);
- if (rc == SOCKET_ERROR)
- {
- fprintf(stderr, "WSAEventSelect failed: %d/n", WSAGetLastError());
- break;
- }
- AssignToFreeThread(newsock);
- }
- }
- }
- }
- }
- WSACleanup();
- return 0;
- }
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
- Windows Socket I/O模型之 WSAEventSelect模式
- vc++ windows socket I/O模型 WSAeventSelect 模型例子
- Socket I/O模型之事件选择(WSAEventSelect)
- Socket I/O模型之事件选择(WSAEventSelect)
- Socket I/O模型之事件选择(WSAEventSelect)
- (三)Socket I/O模型之事件选择(WSAEventSelect)
- Windows socket之WSAEventSelect模型
- Windows socket之WSAEventSelect模型
- Windows socket之WSAEventSelect模型
- Windows socket之WSAEventSelect模型
- Windows Socket I/O模型之 阻塞模式
- Windows Socket I/O模型之 Select模式
- Windows Socket I/O模型之 WSAAsyncSelect模式
- 套接字I/O模型之WSAEventSelect
- 套接字I/O模型之WSAEventSelect
- 套接字I/O模型之WSAEventSelect
- 套接字I/O模型之WSAEventSelect
- 套接字I/O模型之WSAEventSelect
- Windows Socket I/O模型之 阻塞模式
- sicily 1201
- Windows Socket I/O模型之 Select模式
- 祝大家春节快乐,万事如意。
- Windows Socket I/O模型之 WSAAsyncSelect模式
- Windows Socket I/O模型之 WSAEventSelect模式
- Windows Socket I/O模型之 重叠I/O事件通知模式
- Windows Socket I/O模型之 I/O完成端口
- BLOG搬家了
- 差分约束系统
- 地址回调
- 开启页面一段时间自动关闭广告的代码
- s60webkit 渲染流程
- ASP.net mvc 架构中在JQuery脚本与Action传值