본문 바로가기

프로그래밍 언어/C

Socket Programming in C

Socket_Programming_c.pdf
5.59MB

Client-Server 매커니즘

가정 : 서로 다른 네트워크 머신 (M1, M2) 가 상호 소통하는 프로그램을 만들고자 한다. 한 사람이 M1에서 첫번재 프로그램을 시작하면 이 프로그램은 M2에 있는 프로그램으로 메시지를 보낸다. 컴퓨터는 사람보다 빠르기 때문에 M1의 프로그램은 M2로 부터 응답을 받는데 몇 ms 밖에 걸리지 않는다. 두번째 프로그램은 M1으로부터 메시지를 받는데 몇 ms가 걸리고, 첫번째 프로그램이 아직 활성화가 되지 않았다고 결론을 내고 에러 메시지를 보여주고 나간다. 그럼 한쪽은 계속 프로그램을 실행시키더라도 상호소통할 수 없다.

Socket

소캣의 개념

  • 호스트의 네트워크 스택에 연결된 어플리케이션을 위한 인터페이스

소켓 API 

  • 32-bit 노드 주소 IP address
  • 16-bit 포트 넘버

소켓 종류

  • SOCK_STREAM : TCP, 신뢰 가능한 전달, 순서 보장, 연결 지향, 양방향 연결
  • SOCK_DGRAM : UDP, 신뢰 불가능, 순서 보장 X, 받거나 전달할 수 없고 양방향 소통은 불가능

TCP vs. UDP

  • TCP : 용량 큰 데이터를 전달에 사용, 지속적 연결
  • UDP : 빠른 lookup, 하나의 query-response에 사용

소켓 프로그래밍 절차 

socket creation with socket()

int sockid = socket(family, type, protocol);

/*
	sockid : 소켓 구분자, integer
    famliy : integer, 커뮤니케이션 도메인 
    		PF_INET (IPv4, 인터넷 주소) PF_UNIX(로컬 소통, 파일 주소)
    type : SOCK_STREAM, SOCK_DGRAM
    protocol: IPPROTO_TCP, IPPROTO_UDP, 보통 0/ 디폴트로 세팅 
    
    실패 시 -1 반환
    데이터의 목적지나 출발지를 특정하는 콜이 아님 
*/

socket close()

status = close(sockid);

/*
	성공 0, 실패 -1 반환 
    스트림 소켓의 경우 연결이 끊기고 포트 넘버를 해제
*/

specifying address

struct sockaddr {
	unsigned short sa_famliy // address family
    char sa_data[14]; // famliy-specific address information
}

struct in_addr {
	unsigned long s_addr; // 32bit internet addr
}

struct sockaddr_in {
	unsigned short sin_family // internet protocol
    unsigned short sin_port; // address port (16bits)
    struct in_addr sin_addr; // internet addr (32bits)
    char sin_zero[8]; // not used
}

assign address to socket with bind()

int status = bind(sockid, &addrport, size);

/*

	sockid : int
    addrport : sockaddr 구조체, ip 주소, 포트넘버 
    size : byte단위로 addrport 구조체크기 
    
    실패시 -1 반환 

*/

int sockid;
struct sockaddr_in addrport;
sockid = socket(PF_INET, SOCK_STREAM, 0);

addrport.sin_family = AF_INET;
addrport.sin_port = htons(5100);
addrport.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockid, (struct sockaddr *) &addrport, sizeof(addrport)) != -1 ) {
	...
}
  • bind는 두 소켓 타입 모두 스킵 가능
  • datagram 소켓 보내기만 하는건 바인드 필요 없고, 받는건 필요함
  • stream 소켓은 연결 셋팅하는 중에 목적지가 결정됨 그래서 수신지의 포트를 알 필요 없음 

listen()

int status = listen(sockid, queueList);

/*
sockid : integer
queueList: integer, 연결을 기다릴 수 있는 활성화된 참가자들의 수 
listen하고 있으면 0, 에러시 -1 반환 
새로운 소켓을 얻기 위해 서버만! 사용 
*/

establish connection with connect()

int status = connect(sockid, &foreignAddr, addrlen);
/*
sockid 
foreignAddr : sockAddr 구조체, 수동적 참가자의 주소
addrlen : 정수, name의 크기
성공시 0 실패시 -1 반환 
blocking 
*/

accept () : 서버가 들어오는 클라이언트 연결을 위한 소켓을 얻기 위해 호출하는 함수

int s = accept(sockid, &clientAddr, &addrLen);

/*
s : 정수, 새로운 소켓, 데이터 전달을 위해 사용하는 소켓
sockid : 기존에 listen되고 있는 소켓
clienAddr : sockAddr 구조체, 활성화된 참자가의 주소
addrLen : clientAddr의 크기, 
blocking - 반환되기 전에 연결을 기다려야 함
소켓 큐에서 다음 연결을 dequeue
*/

exchange data with stream socket : send(), recv()

int count = send(sockid, msg, msgLen, flags);
/*
msg: const void[], 전달할 메시지 
msgLen : 정수, 전달할 메시지 길이 (바이트)
flags : 정수, 옵션, 디폴트는 0
count : 전달된 바이트 수 / 실패시 -1 반환
*/

int count = recv(sockid, recvBuf, bufLen, flags);
/*
recvBuf : void[], 받은 바이트를 저장
bufLen : 받은 바이트 수 
flags : 정수, 옵션 값, 디폴트 0
count : 받은 바이트 값, 실패시 -1
*/

// 오직 데이터가 전달되거나 받은 이후에만 반환 (blocking) 

exchange data with datagram socket : send(), recv()

int count = sendto(sockid, msg, msgLen, flags, &foreignAddr, addrlen);
/*
foreignAddr : sockaddr 구조체, 목적지 주소
addrLen : foreignAddr의 크기 
*/

int count = recvfrom(sockid, secvDub, dufLen, flags, &clientAddr, addrlen);
/*
clientAddr : 클라이언트 주소
*/

 

Windows socket programming 

 

  • WinSock 2 라이브러리 사용
  • 독립적인 전송 인터페이스 제공하는 프로토콜, 실시간 멀티미디어 소통이 가능한 네트워킹 서비스 
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

WSADA wsadata;
int err;
err = WSAStartup(WSVERS, &wsadata);

if (err != 0) {
	WSACleanup();
    printf("WSAStartup failed with an error: %d\n", err);
}

Practice example

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

Stream socket

Server

1. create a TCP socket

2. assign a port to socket

3. set socket to listen

4. accept new connection

5. communicate

6. close connection

7. repeat 4 5 6

 

Client

1. create a TCP socket

2. establish connection

3. communicate

4. cloase the connection

Datagram socket

자료 참고