使用阻塞模式写的一个带命令行Socket服务器代码

本文介绍了一个基于TCP协议的简单客户端与服务端通信示例。通过命令行参数配置远程端口、服务器IP地址及发送消息次数等,实现客户端向服务端发送消息并接收反馈的功能。代码中涉及Winsock库的初始化、套接字创建、绑定、监听及接受连接请求等步骤。

 

#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;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值