天天看點

使用阻塞模式寫的一個帶指令行Socket伺服器代碼

#include "stdafx.h"

#include <Winsock2.h>

#include <process.h>

#define PORT 5150

#define DATA_BUFSIZE 4096

#define SEND_COUNT   10

DWORD g_dwPort = 1234;

char g_szServer[64] = {0};

BOOL g_bSend = FALSE;

BOOL g_bRecv = FALSE;

DWORD g_dwRecvTimeInterval = 2000;

DWORD g_dwSendTimeInterval = 1000;

DWORD g_dwCount = 99999999;

// Command Line Options:

//    client [-p:x] [-s:IP] [-n:x] [-o]

//           -p:x      Remote port to send to

//           -s:IP     Server's IP address or hostname

//           -n:x      Number of times to send message

//           -o        Send messages only; don't receive

//

// Function: usage:

//

// Description:

//    Print usage information and exit

//

void usage()

{

 printf("usage: client [-p:x] [-s:IP] [-n:x] [-o]/n/n");

 printf("       -p:x      Remote port to send to/n");

 printf("       -i:IP     Server's IP address or hostname/n");

 printf("       -n:x      Number of times to send message/n");

 printf("       -u:x      Send messages time interval;/n");

 printf("       -v:x      Recv messages time interval;/n");

 printf("       -s        Send messages only;/n");

 printf("       -r        Recv messages only;/n");

 ExitProcess(1);

}

//

// Function: ValidateArgs

//

// Description:

//    Parse the command line arguments, and set some global flags

//    to indicate what actions to perform

//

void ValidateArgs(int argc, char **argv)

{

 int                i;

 if (argc == 1)

  usage();

 for(i = 1; i < argc; i++)

 {

  if ((argv[i][0] == '-') || (argv[i][0] == '/'))

  {

   switch (tolower(argv[i][1]))

   {

   case 'p':        // Remote port

    if (strlen(argv[i]) > 3)

     g_dwPort = atoi(&argv[i][3]);

    break;

   case 'i':       // Server

    if (strlen(argv[i]) > 3)

     strcpy(g_szServer, &argv[i][3]);

    break;

   case 'n':       // Number of times to send message

    if (strlen(argv[i]) > 3)

     g_dwCount = atol(&argv[i][3]);

    break;

   case 'r':       // Recv messages only

    g_bRecv = TRUE;

    break;

   case 's':       // Send messages only

    g_bSend = TRUE;

    break;

   case 'u':       // Send messages time interval

    if (strlen(argv[i]) > 3)

     g_dwSendTimeInterval = atol(&argv[i][3]);

    break;

   case 'v':       // Recv messages time interval

    if (strlen(argv[i]) > 3)

     g_dwRecvTimeInterval = atol(&argv[i][3]);

    break;

   default:

    usage();

    break;

   }

  }

 }

}

unsigned __stdcall RecvThreadFunc( void* pArguments )

{

 printf("RecvThreadFunc is running.../r/n");

 if (!g_bRecv)

  goto FUN_END;

 SOCKET sock = (SOCKET)pArguments;

 int nRecvLen = 0;

 char szRecvBuff[1024] = {0};

 while(TRUE)

 {

  memset(szRecvBuff, 0, sizeof(szRecvBuff));

  nRecvLen = recv(sock, szRecvBuff, sizeof(szRecvBuff)-1, 0);

  if (nRecvLen== SOCKET_ERROR)

  {

   DWORD dwErr = WSAGetLastError();

   printf("recv error code: %d/r/n", dwErr);

   break;

  }

  else if (nRecvLen == 0)

  {

   printf("RecvThreadFunc: peer close socket./r/n");

   if (NULL != sock)

   {

    closesocket(sock);

    sock = NULL;

   }

   break;

  }

  printf("recv data: [%d]%s/r/n", nRecvLen, szRecvBuff);

  Sleep(g_dwRecvTimeInterval);

 }

FUN_END:

 printf("RecvThreadFunc is over!/r/n");

 return 0;

}

unsigned __stdcall SendThreadFunc( void* pArguments )

{

 printf("SendThreadFunc is running.../r/n");

 if (!g_bSend)

  goto FUN_END;

 SOCKET sock = (SOCKET)pArguments;

 int nSndLen = 0;

 char szSndBuff[1024] = {0};

 strcpy(szSndBuff, "this is server data.");

 while(g_dwCount-- > 0)

 {

//  printf("send data: %s/r/n", szSndBuff);

  nSndLen = send(sock, szSndBuff, strlen(szSndBuff), 0);

  if (nSndLen == SOCKET_ERROR)

  {

   DWORD dwErr = WSAGetLastError();

   printf("send error code: %d/r/n", dwErr);

   break;

  }

  else if (nSndLen == 0)

  {

   printf("SendThreadFunc: peer close socket./r/n");

   if (NULL != sock)

   {

    closesocket(sock);

    sock = NULL;

   }

   break;

  }

  Sleep(g_dwSendTimeInterval);

 }

FUN_END:

 printf("SendThreadFunc is over!/r/n");

 return 0;

}

int _tmain(int argc, _TCHAR* argv[])

 memset(g_szServer, 0, sizeof(g_szServer));

 ValidateArgs(argc, argv);

 if (strlen(g_szServer) == 0)

  strcpy(g_szServer, "127.0.0.1");

 //----------------------

 // Initialize Winsock.

 WSADATA wsaData;

 int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

 if (iResult != NO_ERROR)

 {

  printf("Error at WSAStartup()/n");

  return 1;

 }

 //----------------------

 // Create a SOCKET for listening for

 // incoming connection requests.

 SOCKET ListenSocket;

 ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

 if (ListenSocket == INVALID_SOCKET)

 {

  printf("Error at socket(): %ld/n", WSAGetLastError());

  WSACleanup();

  return 1;

 }

 //----------------------

 // The sockaddr_in structure specifies the address family,

 // IP address, and port for the socket that is being bound.

 sockaddr_in service;

 service.sin_family = AF_INET;

 service.sin_addr.s_addr = inet_addr(g_szServer);

 service.sin_port = htons(g_dwPort);

 if (bind( ListenSocket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)

 {

  printf("bind() failed./n");

  closesocket(ListenSocket);

  WSACleanup();

  return 1;

 }

 //----------------------

 // Listen for incoming connection requests.

 // on the created socket

 if (listen( ListenSocket, 1 ) == SOCKET_ERROR)

 {

  printf("Error listening on socket./n");

  closesocket(ListenSocket);

  WSACleanup();

  return 1;

 }

 //----------------------

 // Create a SOCKET for accepting incoming requests.

 SOCKET AcceptSocket;

 printf("Waiting for client to connect.../n");

 //----------------------

 // Accept the connection.

 AcceptSocket = accept( ListenSocket, NULL, NULL );

 if (AcceptSocket == INVALID_SOCKET)

 {

  printf("accept failed: %d/n", WSAGetLastError());

  closesocket(ListenSocket);

  WSACleanup();

  return 1;

 }

 else

  printf("Client connected./n");

 HANDLE hThread[2];

 unsigned threadID;

 // Create the recv thread.

 hThread[0] = (HANDLE)_beginthreadex( NULL, 0, &RecvThreadFunc, (LPVOID)AcceptSocket, 0, &threadID );

 // Create the send thread.

 hThread[1] = (HANDLE)_beginthreadex( NULL, 0, &SendThreadFunc, (LPVOID)AcceptSocket, 0, &threadID );

 // Wait until second thread terminates. If you comment out the line

 // below, Counter will not be correct because the thread has not

 // terminated, and Counter most likely has not been incremented to

 // 1000000 yet.

 WaitForMultipleObjects(2, hThread, TRUE, INFINITE);

 // No longer need server socket

 closesocket(ListenSocket);

 WSACleanup();

 return 0;

}