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

本文介绍了一个使用输入/输出完成端口(IOCP)和WinSock库实现的多线程客户端样例程序。该程序能够创建多个线程,每个线程都与服务器进行通信,发送消息并接收回应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值