// Server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
void ErrorHandling(char* message);

int main(int argc, char* argv[]) {
	WSADATA wsaData;
	SOCKET hServSock, hClntSock;
	SOCKADDR_IN servAddr, clntAddr;

	int szClntAddr;
	char message[] = "Hello World!";

	// argc가 2가 아니라면 즉, 포트번호가 설정이 안되었다면 종료
	if (argc != 2) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}
    
	// Winsock 라이브러리의 초기화를 수행
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		ErrorHandling("WSAStartup() error!");
	}
    
	// 소켓을 생성하며, 이 소켓은 서버와 클라이언트 간의 연결에 사용
	hServSock = socket(PF_INET, SOCK_STREAM, 0);
	if (hServSock == INVALID_SOCKET) {
		ErrorHandling("socket() error!");
	}
    
	// servAddr 구조체를 0으로 초기화
	// INADDR_ANY를 사용하여 소켓이 동작하는 컴퓨터의 IP주소를 자동으로 할당
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servAddr.sin_port = htons(atoi(argv[1]));

	// 생성한 소켓에 주소와 포트 번호를 바인딩
	if (bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
		ErrorHandling("bind() error!");
	}

	// 클라이언의 연결 요청을 기다리기 시작
	// 연결 요청 대기 큐의 크기를 5로 설정하여 클라이언트의 연결 요청을 5개까지 대기 가능
	if (listen(hServSock, 5) == SOCKET_ERROR) {
		ErrorHandling("listen() error!");
	}

	// 클라이언트의 연결 요청을 수락하고, 연결된 클라이언트와의 통신을 위한 새로운 소켓을 반환
	szClntAddr = sizeof(clntAddr);
	hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr);
	if (hClntSock == INVALID_SOCKET) {
		ErrorHandling("accept() error!");
	}

	// 연결된 클라이언트에게 "Hello World!" 메시지를 전송
	send(hClntSock, message, sizeof(message), 0);
    
	// 더 이상 필요하지 않은 소켓을 닫기
	closesocket(hClntSock);
	closesocket(hServSock);
    
	// Winsock 라이브러리의 사용을 종료하고, 할당된 리소스를 해제
	WSACleanup();

	return 0;
}

void ErrorHandling(char* message) {
	fputs(message, stderr);
	fputs("\n", stderr);
	exit(1);
}

 

// Client

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
void ErrorHandling(char* message);

int main(int argc, char* argv[])
{
	WSADATA wsaData;
	SOCKET hSocket;
	SOCKADDR_IN servAddr;

	char message[30];
	int strLen = 0;
	int idx = 0, readLen = 0;
	
    // argc가 3이 아니라면 즉, IP와 포트번호가 설정이 안되었다면 종료
	if (argc != 3) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		ErrorHandling("WSAStartup() error!");
	}

	hSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (hSocket == INVALID_SOCKET) {
		ErrorHandling("socket() error!");
	}

	// 사용자가 제공한 IP주소, 포트번호를 알맞는 형식으로 변환
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr(argv[1]);
	servAddr.sin_port = htons(atoi(argv[2]));

	// 위에서 설정한 서버의 주소와 포트번호에 연결 시도
	if (connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
		ErrorHandling("connect() error!");
	}

	// 서버로부터 데이터를 1바이트씩 수신
	while (readLen = recv(hSocket, &message[idx++], 1, 0)) {
		if (readLen == -1) {
			ErrorHandling("read() error!");
		}

		strLen += readLen;
	}

	// 서버로부터 받은 메세지와 길이를 출력
	printf("Message from server: %s \n", message);
	printf("Function read call count: %d", strLen);

	closesocket(hSocket);
	WSACleanup();

	return 0;
}

void ErrorHandling(char* message) {
	fputs(message, stderr);
	fputs("\n", stderr);
	exit(1);
}

포트번호를 9190을 설정한 후 실행 결과

서버에서 설정한 Hello World! 메세지를 클라이언트에서 수신했다.

'네트워크' 카테고리의 다른 글

소켓 프로그래밍 - Iterative 에코 서버  (0) 2023.09.10
ReaderWriterLock 구현  (0) 2023.08.05
ReaderWriterLock  (0) 2023.08.04
AutoResetEvent  (0) 2023.08.03
SpinLock  (0) 2023.08.02

+ Recent posts