IOCP--Windows服务器编程之客户端代码

/*
==========================================================================

Purpose:

This is a sample code that demonstrates for the following:

* Use of the I/O Completion ports with WinSock.  The idea is to create a
  simple application that will use IOCP, highlight how to use IOCP.

Notes:

* The client will make simple socket calls. 
  Let server use IOCP to manage them.

Author:

* Swarajya Pendharkar

Date:

* 10th March 2006

Updates:

* Minor tweaks - 24th March 2006
* Removed a comment - 9th June 2006
* Updates for stress testing, client will keep running till
  we want it to - 19th August 2006
* Client is now multi-threaded - 22th August 2006                     
==========================================================================
*/

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <winsock2.h>

//Buffer Length
#define MAX_BUFFER_LEN 256

CRITICAL_SECTION g_csConsole; //When threads write to console we need mutual exclusion

//Structure to pass information to Thread
struct ThreadInfo
{
     int m_nThreadNo;
     int m_nNoOfSends;
     SOCKET m_Socket;
     char m_szBuffer[MAX_BUFFER_LEN];
};

//global functions
bool CreateConnectedSocket(SOCKET *pSocket, char *szHost, int nPortNo);
void WriteToConsole(char *szBuffer);
DWORD WINAPI WorkerThread(LPVOID lpParam);

int main(int argc, char* argv[])
{
     //Validate the input
     if (argc < 3)
     {
          printf("/nUsage: %s hostname port.", argv[0]);
          return 1; //error
     }
    
     //Initialize Winsock
     WSADATA wsaData;
    
     int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    
     if (NO_ERROR != nResult)
     {
          printf("/nError occurred while executing WSAStartup().");
          return 1; //error
     }
    
     //Initialize the Console Critical Section
     InitializeCriticalSection(&g_csConsole);
    
     int nPortNo = atoi(argv[2]);
    
     char szBuffer[MAX_BUFFER_LEN];
     int nNoOfThreads = 0;
     int nNoOfSends = 0;
    
     printf("/nPlease enter message to be sent to the server: ");
    
     //Read the message from server
     gets(szBuffer);
    
     printf("/nPlease enter number of threads to be created: ");
    
     //No. of times we will send the message to the server
     scanf("%d", &nNoOfThreads);
    
     printf("/nPlease enter number of times the messages needs to be sent: ");
    
     //No. of times we will send the message to the server
     scanf("%d", &nNoOfSends);
    
     HANDLE *p_hThreads = new HANDLE[nNoOfThreads];
     ThreadInfo *pThreadInfo = new ThreadInfo[nNoOfThreads];
    
     bool bConnectedSocketCreated = false;
    
     DWORD nThreadID;
    
     for (int ii = 0; ii < nNoOfThreads; ii++)
     {
          bConnectedSocketCreated = CreateConnectedSocket(&(pThreadInfo[ii].m_Socket), argv[1], nPortNo);
         
          if (!bConnectedSocketCreated)
          {
               //Clean up memory
               delete[] p_hThreads;
               delete[] pThreadInfo;
              
               //failed in creating of connected socket, error out.
               return 1;
          }
         
          //Populate ThreadInfo
          pThreadInfo[ii].m_nNoOfSends = nNoOfSends;
          pThreadInfo[ii].m_nThreadNo = ii+1;
          sprintf(pThreadInfo[ii].m_szBuffer, "Thread %d - %s", ii+1, szBuffer);
         
          //Create thread and start banging the server
          p_hThreads[ii] = CreateThread(0, 0, WorkerThread, (void *)(&pThreadInfo[ii]), 0, &nThreadID);
     }
    
     //Let Worker Threads shutdown
     WaitForMultipleObjects(nNoOfThreads, p_hThreads, TRUE, INFINITE);
    
     //Close the sockets here
     for (ii = 0; ii < nNoOfThreads; ii++)
     {
          closesocket(pThreadInfo[ii].m_Socket);
     }
    
     //Clean up memory
     delete[] p_hThreads;
     delete[] pThreadInfo;
    
     //Delete the Console Critical Section.
     DeleteCriticalSection(&g_csConsole);
    
     //Cleanup Winsock
     WSACleanup();
     return 0;
}

//printf() is not thread safe
void WriteToConsole(char *szBuffer)
{
     EnterCriticalSection(&g_csConsole);
    
     printf("/n%s", szBuffer);
    
     LeaveCriticalSection(&g_csConsole);
}

bool CreateConnectedSocket(SOCKET *pSocket, char *szHost, int nPortNo)
{
     struct sockaddr_in ServerAddress;
     struct hostent *Server;
    
     char szConsole[MAX_BUFFER_LEN];
    
     //Create a socket
     *pSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
     if (INVALID_SOCKET == *pSocket)
     {
          sprintf(szConsole, "Error occurred while opening socket: %d.", WSAGetLastError());
          WriteToConsole(szConsole);
          return false; //error
     }
    
     //Server name will be supplied as a commandline argument
     //Get the server details
     Server = gethostbyname(szHost);
    
     if (Server == NULL)
     {
          closesocket(*pSocket);
          sprintf(szConsole, "/nError occurred no such host.");
          WriteToConsole(szConsole);
          return false; //error
     }
    
     //Cleanup and Init with 0 the ServerAddress
     ZeroMemory((char *) &ServerAddress, sizeof(ServerAddress));
    
     ServerAddress.sin_family = AF_INET;
    
     //Assign the information received from gethostbyname()
     CopyMemory((char *)&ServerAddress.sin_addr.s_addr,
          (char *)Server->h_addr,
          Server->h_length);
    
     ServerAddress.sin_port = htons(nPortNo);
    
     //Establish connection with the server
     if (SOCKET_ERROR == connect(*pSocket, reinterpret_cast<const struct sockaddr *>(&ServerAddress),sizeof(ServerAddress)))
     {
          closesocket(*pSocket);
          sprintf(szConsole, "Error occurred while connecting.");
          WriteToConsole(szConsole);
          return false; //error
     }
    
     return true;
}

DWORD WINAPI WorkerThread(LPVOID lpParam)
{
     ThreadInfo *pThreadInfo = (ThreadInfo*)lpParam;
    
     char szConsole[MAX_BUFFER_LEN];
     char szTemp[MAX_BUFFER_LEN];
    
     int nBytesSent = 0;
     int nBytesRecv = 0;
    
     for (int ii = 0; ii < pThreadInfo->m_nNoOfSends; ii++)
     {
          sprintf(szTemp, "%d. %s", ii+1, pThreadInfo->m_szBuffer);
         
          //Send the message to the server, include the NULL as well
          nBytesSent = send(pThreadInfo->m_Socket, szTemp, strlen(szTemp), 0);
         
          if (SOCKET_ERROR == nBytesSent)
          {
               sprintf(szConsole, "Error occurred while writing to socket %ld.", WSAGetLastError());
               WriteToConsole(szConsole);
               return 1; //error
          }
         
          //Get the message from the server
          nBytesRecv = recv(pThreadInfo->m_Socket, szTemp, 255, 0);
         
          if (SOCKET_ERROR == nBytesRecv)
          {
               sprintf(szConsole, "Error occurred while reading from socket %ld.", WSAGetLastError());
               WriteToConsole(szConsole);
               return 1; //error
          }
         
          //Display the server message
          sprintf(szConsole, "Server sent the following message: %s", szTemp);
          WriteToConsole(szConsole);
     }
    
     return 0; //success
}

你可能感兴趣的:(编程,socket,server,服务器,buffer,winapi)