Sample Code
Windows Driver Samples/ UMDF SocketEcho Sample (UMDF Version 1)/ C++/ Exe/ socketechoserver.cpp/
/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: socketserver.cpp Abstract: A simple socket server application that listens on a specified port and echoes back data received. Environment: User Mode --*/ #include "internal.h" DWORD Run( LPVOID lpThreadParameter ) /*++ Routine Description: This routine is invoked for each thread created for a new connection accepted by the server. The rcv and send to socket happen in this thread routine. Arguments: lpThreadParameter , The Thread parameter which contains socket information Return Value: Thread Exit Code --*/ { #define DeleteBufferExitThread(dwExitCode) \ delete[] buffer; \ buffer = NULL; \ ExitThread(dwExitCode); #define DeleteBufferReturn(dwExitCode) \ delete[] buffer; \ buffer = NULL; \ return dwExitCode; int count =0; char *buffer = new char[DATA_LENGTH]; if (NULL == buffer) { ExitThread(1); } DWORD Event; // // Look at socket information from thread arg. // CEchoServer *pThreadData = (CEchoServer*)lpThreadParameter; if (pThreadData==NULL) { DeleteBufferExitThread(1); } SOCKET sClient = pThreadData->m_socket; HANDLE NetworkEvent = pThreadData->m_NetworkEvent; WSANETWORKEVENTS NetworkEvents; printf("Client Start: 0x%Ix\n", sClient); int actual = 0; for(;;) { if ((Event = WSAWaitForMultipleEvents( 1, &NetworkEvent, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError()); DeleteBufferReturn(0); } if (WSAEnumNetworkEvents(sClient ,NetworkEvent, &NetworkEvents) == SOCKET_ERROR) { printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError()); DeleteBufferReturn(0); } if (NetworkEvents.lNetworkEvents & FD_READ) { if (NetworkEvents.lNetworkEvents & FD_READ && NetworkEvents.iErrorCode[FD_READ_BIT] != 0) { printf("FD_READ failed with error %d\n", NetworkEvents.iErrorCode[FD_READ_BIT]); } else { actual = recv(sClient,buffer,DATA_LENGTH*sizeof(char),0); // // socket connection has been reset ,so bail out . // if (actual == 0 || actual == WSAECONNRESET ) { printf(" Could not get data , Error : 0x%lx \n",WSAGetLastError()); break; // socket shut-down } printf("FD_READ read buffer on client 0x%Ix with length %d \n",sClient,actual); count = send(sClient, (const char*)buffer,actual,0); if ( count == SOCKET_ERROR ) { if ( WSAGetLastError()== WSAEWOULDBLOCK ) { printf(" Could not send data as resource is unavaliable , do not retry until next Write event \n"); } else { printf(" Could not send data , Error : 0x%lx \n",WSAGetLastError()); break; } } else { printf("FD_WRITE write buffer on client 0x%Ix with length %d \n",sClient,count); } } } // // if there is a write network event and there is data to write , write that // if (NetworkEvents.lNetworkEvents & FD_WRITE) { if (NetworkEvents.lNetworkEvents & FD_WRITE && NetworkEvents.iErrorCode[FD_WRITE_BIT] != 0) { printf("FD_WRITE failed with error %d\n", NetworkEvents.iErrorCode[FD_WRITE_BIT]); } else { count = send(sClient, (const char*)buffer,actual,0); if ( count == SOCKET_ERROR ) { if ( WSAGetLastError()== WSAEWOULDBLOCK ) { printf(" Could not send data as resource is unavaliable , do not retry until next Write event "); } else { printf(" Could not send data , Error : 0x%lx \n",WSAGetLastError()); break; } } else { printf("FD_WRITE write buffer on client 0x%Ix with length %d \n",sClient,count); } actual = 0; } } if (NetworkEvents.lNetworkEvents & FD_CLOSE) { shutdown(sClient,FD_READ|FD_WRITE); printf(" recived a close from client : 0x%Ix \n",sClient); closesocket(sClient); DeleteBufferExitThread(0); } } DeleteBufferReturn(1); } CEchoServer::CEchoServer( SOCKET socketclient ) /*++ Routine Description: This is the constructor routine for CEchoServer class. This is called for each instance of new connection accepted by the server . Arguments: Socket received from the accept Return Value: None . --*/ { m_socket = socketclient; m_NetworkEvent = WSACreateEvent(); printf("socket created : 0x%Ix \n", m_socket); } void CEchoServer::Start() /*++ Routine Description: This routine is to Start the thread which will rcv and send the data recieved on this instance of socket connection. Arguments: None. Return Value: None. --*/ { if(WSAEventSelect( m_socket, m_NetworkEvent, FD_READ|FD_WRITE|FD_CLOSE)== SOCKET_ERROR) { printf("Error in Event Select,Cannot start Server thread for this socket \n"); closesocket(m_socket); goto Exit; } // // Create thread to read/write data to this socket // HANDLE hRunThread = CreateThread( NULL, // Default Security Attrib. 0, // Initial Stack Size, (LPTHREAD_START_ROUTINE) Run, // Thread Func this, // Arg to Thread Func. 0, // Creation Flags NULL // Don't need the Thread Id. ); if (NULL == hRunThread) { printf(" Could not create socket server run thread : 0x%lx \n", GetLastError()); closesocket(m_socket); goto Exit; } Exit: return ; } void SocketServerMain( _In_ unsigned short uPort ) /*++ Routine Description: This routine is the main entry for the app when the app is configured to be a socket server. It creates a a listening socket for incoming conenctions. Arguments: uPort - Port Number that the socket server binds to Return Value: None. --*/ { SOCKET ListenSocket; int iResult; #pragma warning( suppress: 24002 ) // suppress warning for IPv6 ,currently IPv4 specific sockaddr_in service ; // Initialize Winsock 2.2 WSADATA wsaData; iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if ( NO_ERROR != iResult ) { printf("Error at WSAStartup() \n"); goto Exit; } // // Create a SOCKET for listening for incoming connection requests. // ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ( INVALID_SOCKET == ListenSocket) { printf("Error at socket(): %ld\n ", WSAGetLastError()); goto Cleanup; } // The sockaddr_in structure specifies the address family, // IP address, and port for the socket that is being bound. service.sin_family = AF_INET; #pragma warning( suppress: 24001 ) // suppress warning for IPv6 service.sin_addr.s_addr = inet_addr("127.0.0.1"); service.sin_port = htons(uPort); if (SOCKET_ERROR == bind( ListenSocket, (SOCKADDR*) &service, sizeof(service) ) ) { printf("bind() failed. \n"); closesocket(ListenSocket); goto Cleanup; } // // Listen for incoming connection requests // on the created socket upto MAX_CONNECTIONS // if ( SOCKET_ERROR == listen( ListenSocket, MAX_CONNECTIONS ) ) { printf("Error listening on socket.\n"); } printf("Listening on socket...\n"); // // Set Socket RCVBUF and SNDBUF size to DATA_LENGTH , so large requests are not fragmented . // int iOptVal; int iOptLen = sizeof(int); if (getsockopt(ListenSocket, SOL_SOCKET, SO_RCVBUF, (char*)&iOptVal, &iOptLen) != SOCKET_ERROR) { printf("SO_RCVBUF value: %ld\n", iOptVal); } iOptVal = DATA_LENGTH; iOptLen = sizeof(int); if (setsockopt(ListenSocket, SOL_SOCKET, SO_RCVBUF, (char*)&iOptVal, iOptLen) != SOCKET_ERROR) { printf("Set SO_RCVBUF: ON\n"); } iOptLen = sizeof(int); if (getsockopt(ListenSocket, SOL_SOCKET, SO_RCVBUF, (char*)&iOptVal, &iOptLen) != SOCKET_ERROR) { printf("SO_RCVBUF Value: %ld\n", iOptVal); } iOptLen = sizeof(int); if (getsockopt(ListenSocket, SOL_SOCKET, SO_SNDBUF, (char*)&iOptVal, &iOptLen) != SOCKET_ERROR) { printf("SO_SNDBUF value: %ld\n", iOptVal); } iOptVal = DATA_LENGTH; iOptLen = sizeof(int); if (setsockopt(ListenSocket, SOL_SOCKET, SO_SNDBUF, (char*)&iOptVal, iOptLen) != SOCKET_ERROR) { printf("Set SO_SNDBUF: ON\n"); } iOptLen = sizeof(int); if (getsockopt(ListenSocket, SOL_SOCKET, SO_SNDBUF, (char*)&iOptVal, &iOptLen) != SOCKET_ERROR) { printf("SO_SNDBUF Value: %ld\n", iOptVal); } // // Loop the server to start accepting connections from clients on this socket // for(;;) { CEchoServer *client = new CEchoServer(accept(ListenSocket,NULL,NULL)); if (client) { printf("Client connected.\n"); client->Start(); // Start receiving/sending data on the socket } } Cleanup: // // Invoke Winsock Cleanup // WSACleanup(); Exit: return; } void Usage() /*++ Routine Description: This routine is invoked to display the usage of this application Arguments: None. Return Value: None . --*/ { printf("\n\n Usage: \n"); printf(" ------ \n\n"); printf(" socketechoapp Display Usage \n"); printf(" socketechoapp -h Display Usage\n"); printf(" socketechoapp -p Start the app as server listening on default port\n"); printf(" socketechoapp -p [port#] Start the app as server listening on this port \n"); } /* */ void __cdecl main( _In_ int argc, _In_reads_(argc) char* argv[] ) /*++ Routine Description: Arguments: None. Return Value: None. --*/ { unsigned short argIndex = 1 ; unsigned short uPort = DEFAULT_PORT_ADDRESS ; if (argc < 2) { Usage(); goto Exit; } // // look at second arg and check for either -h which indicates user asked for help in Usage // of this commandline // if (!strcmp(*(argv+argIndex),"-h")) { Usage(); goto Exit; } // // check if its -p and proceed with otherwise show usage // else if (!strcmp(*(argv+argIndex),"-p")) { // // look at third arg, which should be the port# // if ( ++argIndex < argc ) { uPort = (unsigned short)atoi(*(argv+(argIndex))); } SocketServerMain(uPort); } else { Usage(); goto Exit; } Exit: return; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials