WSAEventSelect模型基于TCP协议的控制台网络通信程序
2013-01-12 22:12
357 查看
//服务端源码 #include <winsock2.h> //这里是winsock2,不是winsock #include <stdio.h> #include <tchar.h> #define PORT 5566 #define MSGSIZE 1024 #pragma comment(lib, "ws2_32.lib") int g_iTotalConn=0; SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];//#define MAXIMUM_WAIT_OBJECTS 64 WSAEVENT g_CliEvenArr[MAXIMUM_WAIT_OBJECTS]; DWORD WINAPI WorkerThread(LPVOID); void Cleanup(int index); void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ WSACleanup( ); return; } char hostname[128]; if(gethostname(hostname,128)==0) { printf("%s\n",hostname);//计算机名字 } struct hostent *pHost = gethostbyname(hostname); for (int i = 0; pHost != NULL && pHost->h_addr_list[i] != NULL; i++) { printf("%s\n",inet_ntoa(*(struct in_addr *)pHost->h_addr_list[i])); } SOCKET sListen,sClient; SOCKADDR_IN local,client; DWORD dwThreadId; int iaddrSize=sizeof(SOCKADDR_IN); sListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); local.sin_addr.S_un.S_addr=htonl(INADDR_ANY); local.sin_family=AF_INET; local.sin_port=htons(PORT); bind(sListen,(struct sockaddr*)&local,iaddrSize); listen(sListen,4); CreateThread(NULL,0,WorkerThread,NULL,0,&dwThreadId); while(1) { sClient=accept(sListen,(struct sockaddr*)&client,&iaddrSize); printf("Accepted client:%s:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); g_CliSocketArr[g_iTotalConn]=sClient; g_CliEvenArr[g_iTotalConn]=WSACreateEvent();//针对使用的每一个套接字,首先创建一个事件对象 /*If no error occurs, WSACreateEvent returns the handle of the event object. Otherwise, the return value is WSA_INVALID_EVENT. To get extended error information, call WSAGetLastError.*/ WSAEventSelect(g_CliSocketArr[g_iTotalConn],g_CliEvenArr[g_iTotalConn],FD_READ|FD_CLOSE); //将事件对象与某个套接字关联在一起,同时注册自己感兴趣的网络事件类型 //#define FD_READ_BIT 0 //#define FD_READ (1 << FD_READ_BIT) 1<<0=1 //#define FD_CLOSE_BIT 5 //#define FD_CLOSE (1 << FD_CLOSE_BIT) 1<<5=32 g_iTotalConn++; } } DWORD WINAPI WorkerThread(LPVOID lpParam) { int ret,index; WSANETWORKEVENTS NetworkEvents;//用于接收套接字上发生的网络事件类型以及可能出现的任何错误代码 char szMsg[MSGSIZE]; while(1) { //等待一个或多个事件对象句柄,并在事先指定的一个或所有句柄进入"已传信"状态后,或在超过了一个规定的时间周期后,立即返回。 ret=WSAWaitForMultipleEvents(g_iTotalConn,g_CliEvenArr,FALSE,1000,FALSE); /* If the WSAWaitForMultipleEvents function succeeds, the return value indicates the event object that caused the function to return. If the function fails, the return value is WSA_WAIT_FAILED. To get extended error information, call WSAGetLastError.*/ /*如果事件数组中有某一个事件被传信了,函数会返回这个事件的索引值,但是这个索引值需要减去预定义值 WSA_WAIT_EVENT_0才是这个事件在事件数组中的位置。*/ if(ret==WSA_WAIT_FAILED||ret==WSA_WAIT_TIMEOUT) { continue; } index=ret-WSA_WAIT_EVENT_0; WSAEnumNetworkEvents(g_CliSocketArr[index],g_CliEvenArr[index],&NetworkEvents); //简述:检测所指定的套接口上网络事件的发生。发生了什么类型的网络事件 if(NetworkEvents.lNetworkEvents & FD_READ)//按位与 // #define FD_READ_BIT 0 // #define FD_READ (1 << FD_WRITE_BIT) 1<<0=1 { ret=recv(g_CliSocketArr[index],szMsg,MSGSIZE,0); /*If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.*/ if(ret==0||(ret==SOCKET_ERROR && WSAGetLastError()==WSAECONNRESET)) { Cleanup(index); } else { szMsg[ret]='\0'; printf("%s\n",szMsg); } } if(NetworkEvents.lNetworkEvents & FD_CLOSE) { Cleanup(index); } } return 0; } void Cleanup(int index) { closesocket(g_CliSocketArr[index]); WSACloseEvent(g_CliEvenArr[index]); if(index<g_iTotalConn-1) { g_CliEvenArr[index]=g_CliEvenArr[g_iTotalConn]; g_CliSocketArr[index]=g_CliSocketArr[g_iTotalConn]; } g_iTotalConn--; }
客户端验证源码
#pragma comment(lib, "Ws2_32.lib") #include <Winsock2.h> #include <stdio.h> const char chIP[20]="127.0.0.1"; void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ WSACleanup( ); return; } SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv;//服务端信息 addrSrv.sin_addr.S_un.S_addr=inet_addr(chIP); addrSrv.sin_port=htons(5566); addrSrv.sin_family=AF_INET; int h=connect(sockClient,(sockaddr*)&addrSrv,sizeof(sockaddr)); if(h==0) printf("connect is successful\n"); else {int k=WSAGetLastError(); printf("%d",k);} while(1) { char sendBuffer[100]={"I am a Client."}; //char recvBuffer[100]={0}; //int j=recv(sockClient,recvBuffer,50,0); //printf("%s",recvBuffer); int p=send(sockClient,sendBuffer,20,0); Sleep(3000); } closesocket(sockClient); WSACleanup(); }
相关文章推荐
- 基于事件的select:WSAEventSelect模型
- 【Linux网络编程】基于TCP协议 I/O多路转接(select) 的高性能回显服务器客户端模型
- 利用WSAEventSelect进行网络通信
- 基于WSAEventSelect模型的服务器设计
- 网络编程五种IO模型之WSAEventSelect模型
- 基于WSAEventSelect模型的服务器设计
- 基于WSAEventSelect模型的TCP服务器实现
- 网络学习之WSAEventSelect模型
- 一个基于线程池的WSAEventSelect模型服务器设计
- 几个网络模型的示例代码(BlockingModel、OverlappedModel、WSAEventSelect、CompletionRoutine)..c++
- WSAAsyncSelect基于异步通知的网络socket通信案例一
- 一个基于线程池的WSAEventSelect模型服务器设计
- 详解WSAEventSelect网络模型
- WSAEventselect模型中各网络事件触发机制
- WSAEventSelect模型中FD_READ 网络事件的处理
- WSAEventselect模型中的一些注意事项(尤其是event和事件的关联与重置;FD_WRITE事件的作用)
- Android中基于TCP协议的网络通信之使用Socket进行通信
- WSAEventSelect模型 ---应用实例,重写TCP服务器实例
- 黑马程序员——Eclipse中用两个控制台测试网络通信程序
- WSAEventSelect(事件选择)模型