[Network] 소켓(Socket)통신

 소켓(Socket)통신이란?

소켓 통신은 컴퓨터 네트워크에서 데이터를 주고받기 위한 기술 중 하나로, 클라이언트와 서버 간에 데이터를 교환하는 데 사용된다. 네트워크를 통해 데이터를 안정적으로 전송하고 수신하기 위한 프로그래밍 인터페이스 및 메커니즘이다.

소켓은 응용 프로그램에서 TCP/IP를 이용하는 창구 역할을 하며 응용 프로그램과 소켓 사이의 인터페이스 역할을 담당한다.

소켓통신의 흐름

- 서버

1) socket() : 클라이언트와 서버를 연결할 연결용 소켓을 생성한다.

2) bind() : IP와 Port 번호를 결합한다.

3) listen() : 클라이언트의 접근 요청을 수신하는 대기열을 만들어 몇 개의 클라이언트를 대기 시킬지 결정한다.

               클라이언트가 connect() 해오기 전까지 대기하기 때문에 listen()은 별도 스레드를 만들어서 처리한다고 한다.

4) accept() : 새로운 소켓을 만들어 클라이언트와 실질적인 연결을 수행한다.

 

- 클라이언트

1) socket() : 소켓을 생성한다.

2) connect() : 통신할 서버에 설정된 ip와 port 번호에 통신을 시도한다.

3) 통신 시도 시, 서버가 accept() 함수로 클라이언트의 socket descriptor를 반환한다.

4) 이를 통해서 클라이언트와 서버가 read(), write() 를 통해서 통신을 할 수 있다.

 

통신이 끝나면

 

클라이언트와 서버는 각각 close() 함수를 통해서 연결을 종료한다.

 

 

소켓통신 사용 예제(채팅 프로그램)

// client
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void ErrorHandling(char* message);

int main(int argc, char *argv[]) {
	
	WSADATA wsaData;
	SOCKET hSocket;
	SOCKADDR_IN servAddr;
	
	char message[30];
	char tmp[100];
	int strLen;
	
	if(argc!=3){
		printf("Usage : %s <IP> <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!");
	
	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!");
	
	while(1){
		printf("Message from server >>");
		gets(tmp);
		send(hSocket, tmp, strlen(tmp)+1,0);
		strLen = recv(hSocket, message, sizeof(message)-1, 0);
		if(strLen <= 0)
			ErrorHandling("read() error!");
		printf("Message from server : %s \n", message);
	}
	
	closesocket(hSocket);
	WSACleanup();
	
	return 0;
}

void ErrorHandling(char* message){
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}
// server
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h> // 윈도우즈기 때문에 들어 감 

void ErrorHandling(char * message);

int main(int argc, char *argv[]) {
	
	WSADATA wsaData; // 윈도우즈최적화 
	SOCKET hServSock, hClntSock;
	SOCKADDR_IN servAddr, clntAddr;
	
	int szClntAddr;
	char message[30];
	int strLen;
	
	
	if(argc != 2){
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	} 
	// 윈도우즈이기 때문에 WSAStartup 이 들어감.
	//소켓 만들기 전에 들어가는데, MAKEWORD 는 버전 확인용이라고 생각하면 된다. 
	if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
		ErrorHandling("WSAStartup() error!");
	
	hServSock = socket(PF_INET, SOCK_STREAM, 0);
	if(hServSock == INVALID_SOCKET)
		ErrorHandling("socket() error");
	
	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");
	
	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");
	while(1){
		memset(message, '\0', 30);
		strLen = recv(hClntSock, message, sizeof(message)-1, 0);
		if(strLen == -1)
			ErrorHandling("read() error!");
		printf("Message from client : %s \n", message);
		printf("Message from client >>");
		gets(message);
		send(hClntSock,message,strlen(message)+1,0);
		
	}
	
	closesocket(hClntSock);
	closesocket(hServSock);
	WSACleanup();
	
	return 0;
}

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

 

결과

client

 

server

'Network' 카테고리의 다른 글

[Network] 네트워크 규칙(프로토콜, OSI모델과 TCP/IP모델)  (0) 2023.07.17
[Network] 네트워크 구성  (2) 2023.07.14
[Network] LAN과 WAN  (0) 2023.07.13
[Network] 비트와 바이트  (0) 2023.07.12
[Network] 네트워크의 구조  (0) 2023.07.11