https://pupuduck.tistory.com/85에서 다뤘듯 fdopen 함수로 파일 디스크립터를 FILE형 포인터로 변환시킬 수 있습니다. 그리고 https://pupuduck.tistory.com/70에서 입출력 스트림 분리와 분리했을 때의 장점을 다뤘습니다. 위 글에서는 스트림 분리목적으로 입출력 루틴 독립을 통한 편의성을 느리고, 입력에 상관없이 출력이 가능하게 함으로 속도의 향상을 기대할 수 있었는데, 이 글에서는 읽기모드와 쓰기모드를 구분해야 하는 FILE 포인터를 사용하므로 두 모드의 구분을 통한 편의성 증대와 버퍼링 기능의 향상을 기대할 수 있습니다. 분리된 파일 포인터와 파일 디스크립터, 소켓의 관계는 위와 같이 표현됩니다. 그런데 만약, Half-close를 위해서, 예를 들어 ..
현생/TCP 소켓 프로그래밍
표준 입출력 함수의 장점은 이식성이 좋고, 버퍼링을 통해 성능을 향상시킬 수 있습니다. 소켓을 생성할 때 운영체제는 입출력을 위한 버퍼를 생성하는데, 표준 입출력 함수를 사용하면 추가 버퍼를 제공받습니다. 만약 문자열을 전송한다고 할 때, 먼저 표준 입출력 함수의 버퍼에 저장된 후 소켓의 출력버퍼로 이동한 후 전송됩니다. 버퍼링을 통해 전송하는 데이터를 묶어서 출력 버퍼로 보냄으로 출력버퍼로 데이터 이동 횟수가 줄어들어서 성능을 향상시키게 됩니다. 1바이트를 10회 이동시키는 시간이 10바이트를 1회 이동시키는 시간보다 10배 가까운 시간이 소모된다고 합니다. 표준 입출력 함수의 단점은 양방향 통신이 쉽지 않고, 상황에 따라 fflush함수(파일 스트림 버퍼를 비우는 함수)를 자주 사용하게 되며, 파일 ..
멀티캐스트 멀티캐스트 서버가 멀티캐스트 그룹에게 데이터를 전송하면 그룹의 클라이언트는 모두 데이터를 수신합니다. 멀티캐스트 그룹의 수는 IP 주소 범위 내에서 무제한으로 추가할 수 있습니다. (데이터를 수신하려면 멀티캐스트의 그룹에 가입하면 됩니다.) 멀티캐스트는 UDP를 기반으로 하지만 UDP패킷과 다르게 하나의 패킷만 네트워크에 띄워놓으면 라우터들이 패킷을 복사해서 호스트들에게 전달합니다. 멀티캐스트 패킷의 전송을 위해선 TTL 설정이 필요한데, Time To Live의 약자로 정수로 표현되며 라우터를 하나 거칠 때마다 1씩 감소합니다. 만약 0이된다면 패킷은 더 이상 전달되지 않습니다. int send_sock; int time_live=64; ... send_sock=socket(PF_INET,S..
write & read 지금까지 써온 입출력 함수입니다. 리눅스에선 소켓을 파일처럼 다룰 수 있다는 점을 이용해 파일 입출력 함수를 사용해왔습니다. #include //입력 함수 - success: 전달한 바이트 수, fail: -1 ssize_t write(int fd, const void *buf, size_t nbytes); //출력 함수 - success: 수신한 바이트 수(EOF 전송 시 0), fail: -1 ssize_t read(int fd, void *buf, sized_t nbytes); send & recv #include //입력 함수 - success: 전송된 바이트 수, fail: -1 ssize_t send(int sockfd, const void *buf, size_t nby..
멀티플렉싱이란 하나의 통신채널을 통해 둘 이상의 데이터를 전송하는데 사용되는 기술입니다. 앞서 사용한 멀티프로세스와 달리 프로세스를 생성하지 않고 다수의 클라이언트에게 서비스를 제공할 수 있습니다. 멀티플렉싱 서버를 구현함에 있어서 가장 대표적인 방법으로는 select 함수를 사용하는 것입니다. select 함수를 호출해서 결과를 얻기까지의 과정을 간단하게 정리하면 다음과 같습니다. 1-1 파일 디스크립터의 설정 1-2 검사의 범위 지정 1-3 타임아웃의 설정 2-1 select 함수의 호출 3-1 호출 결과 확인 위 과정을 순서대로 소개하겠습니다. 1-1 파일 디스크립터 설정 select 함수를 사용하면 여러 개의 파일 디스크립터를 모와서 동시에 이들을 관찰할 수 있고, 관찰할 수 있는 항목(=이벤트)..
fork 함수를 통해 복사된 자식 프로세스는 부모 프로세스와 메모리 공간을 공유하지 않으므로 프로세스간 통신은 운영체제의 도움으로 이루어져야 합니다. 이 때 사용하는 것이 파이프입니다. 파이프는 운영체제가 마련해 준 메모리 공간을 통해 프로세스간 통신이 가능하도록 도와줍니다. #include int pipe(int filedes[2]); //success:0 fail:-1 위 함수를 호출하면 인자로 들어간 배열 두 칸에는 각각의 파일 디스크립터가 담깁니다. 0번째 파일 디스크립터는 데이터 수신하는데 사용되고, 1번째는 데이터를 전송하는데 사용됩니다. 즉 1번은 입구, 0번은 출구가 됩니다. 즉 위와 같은 모양이 됩니다. 만약 부모프로세스에서 1번칸으로써 파이프에 입력을 했다면 자식프로세스는 0번칸으로써 ..
이 글에는 멀티프로세스 생성 방법에 대한 설명 없이 응용만 합니다. 따라서 멀티프로세스 생성 방법 등은 아래를 참고해주세요. https://pupuduck.tistory.com/63 https://pupuduck.tistory.com/66 지금까지 구현한 에코 클라이언트의 입출력 방식은 입력 -> 데이터가 수신되길 계속 기다림 -> 수신되면 출력 을 반복해왔습니다. 만약 데이터가 수신되지 않는다면 더 이상 입력은 하지 못합니다. 따라서 입출력 루틴을 분할하게 되면 데이터 수신여부와 관계없이 입력을 할 수 있습니다. 또, 입력부와 출력부를 따로 구현할 수 있는 편의성을 갖게 되고, 데이터 송수신이 잦은 프로그램의 성능이 향상됩니다. 송수신 시간을 기다리지 않아, 동일한 시간 내 데이터 송수신 분량이 많아지..
10-4, 10-5에서 쓰인 시그널 핸들링을 이용하면 멀티 프로세스 기반의 다중접속 서버를 구현할 수 있습니다. 위 그림은 이번에 구현할 멀티프로세스 기반 다중접속 에코 서버의 구현모델입니다. 클라이언트의 수가 둘이면 두 개의 자식 프로세스, 다섯이면 5 개의 자식 프로세스를 가지게 됩니다. 따라서 에코서버는 다음의 과정을 거쳐야 합니다. 1. 에코 서버의 부모프로세스는 accept 함수 호출을 통해 연결 요청 수락 2. 이때 얻게 되는 소켓의 파일 디스크립터 자식 프로세스 생성 후 넘겨줌 3. 자식 프로세스는 전달받은 파일 디시크립터를 바탕으로 서비스 제공 여기서 2번은 자식 프로세스는 생성될 때 부모 프로세스를 전부 복사하므로 따로 처리할 과정은 없습니다. #include #include #inclu..