소켓 프로그래밍
TCP/IP 통신 함수 사용하는 순서
Server | Client | |
Socket() Bind() Listen() Accept() Send() / Recv() Close() |
<- <-> |
Socket() Connect() Send() / Recv() Close() |
socket() : 소켓 생성
형태 : int socket(int domain, int type, int protocol);
int domain : 인터넷을 통해 통신할 지, 같은 시스템 내에서 통신할지 여부 설정
domain | domain 내용 |
PF_INET, AF_INET | IPv4 인터넷 프로토콜을 사용합니다. |
PF_프로토콜 패밀리, AF_주소 패밀리
int type : 데이터의 전송 형태를 지정
type | type 내용 |
SOCK_STREAM | TCP/IP 프로토콜을 이용합니다. |
SOCK_DGRAM | UDP/IP 프로토콜을 이용합니다. |
int protocol : 통신에 있어 특정 프로토콜을 사용을 지정하기 위한 변수, 보통 0 값을 사용
반환
-1 : 에러 그외 : 소켓 식별자
ex)
SOCKET serverSocket;
//AF_INET == PF_INET
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET)
ErrorExit("socket");
else OKMsg("socket");
bind() : 소켓에 정보 지정
형태 : int bind(int socketfd, struct sockaddr* address, socklen_t addressLength);
int socketfd : socket()으로 생성한 소켓명
struct sockaddr* address : 주소 정보를 담은 구조체
struct | struct 내용 |
sockaddr | 기본 구조체 |
socklen_t addressLength : address 구조체의 크기
반환
-1 : 에러 0 : 성공
ex)
SOCKADDR_IN serverAddress = { 0 };
serverAddress.sin_family = AF_INET; //IPv4 인터넷 프로토콜
serverAddress.sin_port = htons(SERVER_PORT); //사용할 포트 지정(server_port)
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); //현재 통신할 IPv4주소
à같은문장 serverAddress.sin_addr.s_addr = inet_addr(SERVER_IP); //통신할 서버 지정
result = bind(serverSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress));
if (result == SOCKET_ERROR)
ErrorMsg("bind");
else OKMsg("bind");
serverAddress.sin_addr.s_addr = inet_addr(SERVER_IP); 이 문장을 아래와 같이 변경 가능
result = inet_pton(AF_INET, SERVER_IP, &(serverAddress.sin_addr));
if (result == -1) ErrorMsg("inet_pton");
else OKMsg("inet_pton");
SockAddr_IN : 소켓에 주소와 포트를 할당하기 위해 사용하는 구조체+++
htonl(INADDR_ANY), Inet_addr(“고정IP”) : 실행되는 시스템마다 IP가 다를 수 있으므로 htonl사용이 편리
listen() : 클라이언트의 접속 요청 확인
형태 : int listen(int socket, int backlog);
int socket : socket()으로 생성한 소켓명
int backlog : 대기 메시지 큐의 개수
반환
-1 : 에러 0 : 성공
ex)
result = listen(serverSocket, 5);
if (result == SOCKET_ERROR)
ErrorMsg("listen");
else OKMsg("listen");
accept() : 클라이언트의 접속요청 허락, 통신용 소켓 생성
형태 : int accept(int socket, struct sockaddr *addr, socklen_t *addrlen);
int socket : socket()으로 생성한 소켓명
struct sockaddr *addr : 클라이언트 주소정보를 가지고 있는 sockaddr 구조체 포인터(주소)
socklen_t *addrlen : 포인터가 가르키는 구조체의 크기
반환
-1 : 에러 클라이언트와의 통신 소켓 : 성공
ex)
SOCKET clientSocket;
SOCKADDR_IN clientAddress = { 0 };
int sizeClient = sizeof(clientAddress);
clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddress, &sizeClient);
if (clientSocket == INVALID_SOCKET)
ErrorMsg("accept");
else OKMsg("accept");
printf("client(IP:%s,PORT:%d)accepted\n", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));
printf("client(IP:%s,PORT:%d)accepted\n", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));
이 문장을 아래와 같이 변경 가능
char clientIP[20] = { 0 };
if (inet_ntop(AF_INET, &(clientAddress.sin_addr), clientIP, sizeof(clientIP)) == NULL)
ErrorMsg("inet_ntop");
else OKMsg("inet_ntop");
send() / recv() : 정보를 주고 받기
형태 : int send(int socket, const void *msg, size_t len, int flags);
int recv(int socket, void *buf, size_t len, int flags);
Send - 정보를 받는 소켓주소(서버)
Recv - 정보를 보내는 소켓주소(클라이언트)
int socket : socket()으로 생성한 소켓명
const void *msg : 상대에게 보낼 자료의 포인터(주소)
size_t len : 전송되는 메시지의 크기(byte 단위)
int flags : 플래그(옵션)
void *buf : 받은 메시지를 저장할 버퍼 포인터(주소)(클라이언트)
반환
-1 : 에러 실제 송수신한 바이트 수 : 성공
ex)
RECV() : 데이터를 받을 소켓 주소
int data = -234;
result = recv(clientSocket, (char*)&data, sizeof(data), 0);
if (result == SOCKET_ERROR)
ErrorMsg("recv");
else OK("recv");
printf("server send data : %d\n", data);
SEND() : 데이터를 보낼 소켓 주소
int data = 100;
result = send(clientSocket, (char*)&data, sizeof(int), 0);
if (result == SOCKET_ERROR)
ErrorMsg("send");
else OK("send");
closesocket() : 소켓 삭제(종료)
형태 : int closesocket(SOCKET sock);
SOCKET sock : 삭제할 소켓명
반환
-1 : 에러 그외 : 성공
ex)
result = closesocket(clientSocket);
if (result == SOCKET_ERROR)
ErrorMsg("closesocket-client");
else OK("closesocket-client");
connect() : 클라이언트에서 서버에 연결 요청하기 (클라이언트 함수)
형태 : int connect(int socket, const struct sockaddr *server_address, socklen_t addrlen);
int socket : socket()으로 생성한 소켓명
const struct sockaddr *server_address : 서버의 주소를 가지고 있는 sockaddr구조체 포인터(주소)
socklen_t addrlen : 포인터가 가리키는 구조체의 크기
반환
-1 : 에러 0 : 성공
ex)
SOCKADDR_IN serverAddress = { 0 };
serverAddress.sin_family = PF_INET;
serverAddress.sin_port = htons(SERVER_PORT);
serverAddress.sin_addr.s_addr = inet_addr(SERVER_IP);
result = connect(clientSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress));
if (result == SOCKET_ERROR)
ErrorMsg("connect");
else OK("connect");