소켓(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);
}
결과
'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 |