[TCP/IP] 에코서버 & 클라이언트 – Single Process 2015-05-19

서버

/*
## 소켓 서버 : 1 v 1 - Single Process
1. socket()			: 소켓생성
2. bind()			: 소켓설정
3. listen()			: 수신대기열생성
4. accept()			: 연결대기
5. read()&write()
	WIN recv()&send	: 데이터 읽고쓰기
6. close()
	WIN closesocket	: 소켓종료
*/

#include "stdafx.h"
#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")

#define MAX_BUFFER		1024
#define SERVER_PORT		3500

int _tmain(int argc, _TCHAR* argv[])
{
	// Winsock Start - windock.dll 로드
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
	{
		printf("Error - Can not load 'winsock.dll' file\n");
		return 1;
	}

	// 1. 소켓생성	
	SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (listenSocket == INVALID_SOCKET)
	{
		printf("Error - Invalid socket\n");
		return 1;
	}

	// 서버정보 객체설정
	SOCKADDR_IN serverAddr;
	memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
	serverAddr.sin_family = PF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	// 2. 소켓설정
	if (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
	{
		printf("Error - Fail to bind\n");
		// 6. 소켓종료
		closesocket(listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}

	// 3. 수신대기열생성
	if (listen(listenSocket, 5) == SOCKET_ERROR)
	{
		printf("Error - Fail to listen\n");
		// 6. 소켓종료
		closesocket(listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}

	// 4. 연결대기
	SOCKADDR_IN clientAddr;
	int addrLen = sizeof(SOCKADDR_IN);
	memset(&clientAddr, 0, addrLen);
	SOCKET clientSocket = accept(listenSocket, (struct sockaddr *)&clientAddr, &addrLen);

	// 5. 데이터 전달
	while (1){
		if (clientSocket != INVALID_SOCKET)
		{
			// 5-1. 데이터 읽기
			char messageBuffer[MAX_BUFFER];
			int receiveBytes = recv(clientSocket, messageBuffer, MAX_BUFFER, 0);
			if (receiveBytes > 0)
			{
				printf("TRACE - Receive message : %s (%d bytes)\n", messageBuffer, receiveBytes);
				// 5-2. 데이터 쓰기
				int sendBytes = send(clientSocket, messageBuffer, strlen(messageBuffer), 0);
				if (sendBytes > 0)
				{
					printf("TRACE - Send message : %s (%d bytes)\n", messageBuffer, sendBytes);
				}
			}
		}
	}

	// 6-1. 클라이언트 소켓종료
	closesocket(clientSocket);

	// 6-2. 리슨 소켓종료
	closesocket(listenSocket);

	// Winsock End
	WSACleanup();

	return 0;
}

클라이언트

/*
## 소켓 클라이언트 : 1 v 1
1. socket()			: 소켓생성
2. connect()		: 연결요청
3. read()&write()
	WIN recv()&send	: 데이터 읽고쓰기
4. close()
	WIN closesocket	: 소켓종료
*/

#include "stdafx.h"
#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")

#define MAX_BUFFER		1024
#define SERVER_IP		"127.0.0.1"
#define SERVER_PORT		3500

int _tmain(int argc, _TCHAR* argv[])
{	
	// Winsock Start - winsock.dll 로드
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0)
	{
		printf("Error - Can not load 'winsock.dll' file\n");
		return 1;
	}

	// 1. 소켓생성
	SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (listenSocket == INVALID_SOCKET)
	{
		printf("Error - Invalid socket\n");
		return 1;
	}

	// 서버정보 객체설정
	SOCKADDR_IN serverAddr;
	memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);

	// 2. 연결요청
	if (connect(listenSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
	{
		printf("Error - Fail to connect\n");
		// 4. 소켓종료
		closesocket(listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}
	else
	{
		printf("Server Connected\n* Enter Message\n->");
	}
	
	while (1)
	{		
		// 메시지 입력
		char messageBuffer[MAX_BUFFER];
		int i, bufferLen;
		for (i = 0; 1; i++)
		{
			messageBuffer[i] = getchar();
			if (messageBuffer[i] == '\n')
			{
				messageBuffer[i++] = '\0';
				break;
			}
		}
		bufferLen = i;
		
		// 3-1. 데이터 쓰기
		int sendBytes = send(listenSocket, messageBuffer, bufferLen, 0);
		if (sendBytes > 0)
		{
			printf("TRACE - Send message : %s (%d bytes)\n", messageBuffer, sendBytes);
			// 3-2. 데이터 읽기
			int receiveBytes = recv(listenSocket, messageBuffer, MAX_BUFFER, 0);
			if (receiveBytes > 0)
			{
				printf("TRACE - Receive message : %s (%d bytes)\n* Enter Message\n->", messageBuffer, receiveBytes);
			}			
		}
		
	}		

	// 4. 소켓종료
	closesocket(listenSocket);

	// Winsock End
	WSACleanup();
	
	return 0;
}

[nGrinder] 2-3. Monitor 설치 2015-05-07

Agent 설치와 동일하게 [2-1. Controller]에서 설치한 컨트롤러 서버로 부터 설치 파일을 다운로드 받아 압축을 풀고 실행한다. 별다른 설정은 필요없다.

 

 1. 다운로드 및 압축해제
cd /usr/local/src
wget http://{Controller Host}/monitor/download
mv download monitor.tar.gz
tar xvf monitor.tar.gz
ngrinder-monitor 폴더가 생성된다.

 

 2. 생성된 폴더를 적당한 위치에 옮기고 monitor를 실행
mv ngrinder-monitor ../
cd /usr/local/ngrinder-monitor
./run_monitor.sh or ./run_monitor_bg.sh
백그라운드로 실행(run_monitor_bg.sh)하지 않고 로그를 실시간으로 확인하기 위해서는 run_monitor.sh를 실행한다.

 

[nGrinder] 2-2. Agent 설치 2015-05-07

[2-1. Controller]에서 설치한 컨트롤러 서버로 부터 설치 파일을 다운로드 받아 압축을 풀고 실행한다. 별다른 설정 필요없이 자동으로 컨트롤러 서버에 연결된다.

 

 1. 다운로드 및 압축해제
cd /usr/local/src
wget http://{Controller Host}/agent/download
mv download agent.tar.gz
tar xvf agent.tar.gz
ngrinder-agent 폴더가 생성된다.

 

 2. 생성된 폴더를 적당한 위치에 옮기고 agent를 실행
mv ngrinder-agent ../
cd /usr/local/ngrinder-agent
./run_agent.sh or ./run_agent_bg.sh
백그라운드로 실행(run_agent_bg.sh)하지 않고 로그를 실시간으로 확인하기 위해서는 run_agent.sh를 실행한다.

 

 3. 많은 쓰레드를 실행할 수 있도록 설정을 변경한다.

ngrinder_agent2

# 확인
ulimit -a
# 설정
vi /etc/security/limits.conf
ulimit -a에서 확인한 값중 max user processes와 open files 두값이 10000이하일 경우 /etc/security/limits.conf 파일을 다음과 같이 수정
 ※ 다른계정으로 실행되기를 원한다면 root 대신 다른계정을 입력
root          soft          nproc          32768
root          hard          nproc          32768
root          soft          nofile         16000
root          hard          nofile         16000

 

 4. 컨트롤러의 Agent Management 메뉴에서 접속 되었음을 확인

ngrinder_agent