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