C++ #16 TCP 에코 통신

underlier12·2020년 3월 5일
1

C++

목록 보기
16/19
post-custom-banner

16. TCP 에코 통신 프로그램

솔루션 생성

하나의 솔루션에 두개의 프로젝트를 생성한다. 하나는 Server로 Client로부터 오는 메세지를 받아 다시 전달하는 역할이며 다른 하나는 Client가 된다. 솔루션 탐색기에 보이는 모습은 다음과 같다.

이때 각 프로젝트마다 Winsock2 라이브러리를 종속시켜주어야 한다. 명칭은 ws2_32.lib이다.

Server

이전 시간의 내용인 socket(), bind(), listen()등의 메소드들이 포함되어 있다.

#include<iostream>
#include<string>
#include<winsock2.h>

using namespace std;

void ShowErrorMessage(string message)
{
	cout << "[오류발생]: " << message << '\n';
	system("pause");
	exit(1);
}

int main()
{
	WSADATA wsaData;
	SOCKET serverSocket, clientSocket;
	SOCKADDR_IN serverAddress, clientAddress;

	int serverPort = 9876;
	char received[256];

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) // Winsock을초기화합니다.
		ShowErrorMessage("WSAStartup()");

	serverSocket = socket(PF_INET, SOCK_STREAM, 0); // TCP 소켓을생성합니다.

	if (serverSocket == INVALID_SOCKET)
		ShowErrorMessage("socket()");

	memset(&serverAddress, 0, sizeof(serverAddress));
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); // 4바이트정수를네트워크바이트형식으로
	serverAddress.sin_port = htons(serverPort); // 2바이트정수네트워크바이트형식으로

	if (bind(serverSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
		ShowErrorMessage("bind()");
	cout << "[현재상태] bind()\n";

	if (listen(serverSocket, 5) == SOCKET_ERROR)
		ShowErrorMessage("listen()");
	cout << "[현재상태] listen()\n";

	int sizeClientAddress = sizeof(clientAddress);
	clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddress, &sizeClientAddress);
	cout << "[현재상태] accept()\n";

	if (clientSocket == INVALID_SOCKET)
		ShowErrorMessage("accept()");

	while (1) { // 클라이언트의메시지를받아서그대로다시전달합니다.
		int length = recv(clientSocket, received, sizeof(received), 0);
		received[length] = NULL;
		cout << "[클라이언트메시지]: " << received << '\n';
		cout << "[메시지전송]: " << received << '\n';
		if (strcmp(received, "[exit]") == 0) {
			send(clientSocket, received, sizeof(received) - 1, 0);
			cout << "[서버종료]\n";
			break;
		}
		send(clientSocket, received, sizeof(received) - 1, 0);
	}
	closesocket(clientSocket);
	closesocket(serverSocket);
	WSACleanup();
	system("pause");

	return 0;
}

Client

클라이언트 측에는 connect(), send() 등의 메소드를 포함한다.

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<string>
#include<winsock2.h>

using namespace std;
void ShowErrorMessage(string message)
{
	cout << "[오류발생]: " << message << '\n';
	system("pause");
	exit(1);
}

int main()
{
	WSADATA wsaData;
	SOCKET clientSocket;
	SOCKADDR_IN serverAddress;
	int serverPort = 9876;
	char received[256];
	string sent;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) // Winsock을초기화합니다.
		ShowErrorMessage("WSAStartup()");
	clientSocket = socket(PF_INET, SOCK_STREAM, 0); // TCP 소켓을생성합니다.
	if (clientSocket == INVALID_SOCKET)
		ShowErrorMessage("socket()");
	memset(&serverAddress, 0, sizeof(serverAddress));
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); // 문자열IP를네트워크바이트형식으로
	serverAddress.sin_port = htons(serverPort); // 2바이트정수네트워크바이트형식으로

	if (connect(clientSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
		ShowErrorMessage("connect()");
	cout << "[현재상태] connect()\n";
	while (1) { // 반복적으로서버로메시지를전송하고에코메시지를전달받습니다.
		cout << "[메시지전송]: ";
		getline(cin, sent);
		if (sent == "") continue;
		send(clientSocket, sent.c_str(), sent.length(), 0);
		int length = recv(clientSocket, received, sizeof(received), 0);
		received[length] = '\0';
		if (strcmp(received, "[exit]") == 0) {
			cout << "[서버종료]\n";
			break;
		}
		cout << "[서버메시지]: " << received << '\n';
	}
	closesocket(clientSocket);
	WSACleanup();
	system("pause");
	return 0;
}

솔루션 빌드

동일 솔루션이 두 개의 프로젝트를 포함하고 있어 솔루션을 빌드하면 자동으로 각기 exe 파일이 생성된다.

profile
logos and alogos
post-custom-banner

1개의 댓글

comment-user-thumbnail
2021년 4월 6일

안녕하세요! 올려주신 코드 도움이 많이 되었습니다! 예제를 통해 TCP통신 연결 및 채팅형태로 가는 부분까지 확인을 했는데요! 여쭤보고 싶은게 있어서 문의드립니다

아래 코드와 같이 정의된 데이터 값들인 intensity4.at(l), range4.at(l), horizontal_a4.at(l) 이것들을 엔터 없이 while loop가 돌면서 실시간 통신으로 보내주고 싶은데, 혹시 도움을 주실 수 있을까요..??

vector intensity4, range4, horizontal_a4, vertical_a4;
while (true){
instance4->getSphericalOutputsWithIntensity(intensity4, range4, horizontal_a4);
int size_buffer4(static_cast(range4.size()));
int l(0); l < size_buffer4; l++;
cout << "Lidar_No4, " << intensity4.at(l) << ", " << range4.at(l) << ", " << horizontal_a4.at(l) << endl; }

알려주신 아래의 Data send 부분을 while에 넣어 돌리면 데이터 값은 가지않고, 제가 타이핑한 문자만 가더라고요 ㅠㅠ 제가 선언한 데이터 값을 보내주고 싶은데 알려주시면 감사하겠습니다!!

///Data send
getline(cin, sent);
if (sent == "") continue;
send(clientSocket, sent.c_str(), sent.length(), 0);

답글 달기