C/TCPIP 소켓 프로그래밍(윤성우 저)

TCP/IP 소켓 프로그래밍 5장 내용 확인문제

꾸준함. 2017. 5. 25. 18:16

1. TCP 소켓의 연결설정 과정인 Three-way handshaking에 대해서 설명해 보자. 특히 총 3회의 데이터 송수신이 이뤄지는데, 각각의 데이터 송수신 과정에서 주고 받는 데이터에 포함된 내용이 무엇인지 설명해 보자.


>

호스트 A가 호스트 B에게 전달하는 메세지를 SYN이라고 한다. 이렇듯 호스트 A가 호스트 B에게 전송하는 데이터의 동기화를 위해서 처음 보내는 '동기화 메세지'를 가리켜 SYN이라고 한다. 이어서 호스트 B가 호스트 A에게 전달하는 메세지를 가리켜 SYN+ACK라고 한다. 이는 처음으로 보내는 동기화 메세지와 앞서 수신한 메세지에 대한 응답의 내용까지 포함되어 있기 때문이다. 그리고 마지막으로 호스트 A가 호스트 B에게 전달하는 메세지에는 동기화 정보가 포함되어 있기 때문에 ACK라고 한다.


2. TCP는 데이터의 전송을 보장하는 프로토콜이다. 그러나 인터넷을 통해서 전송되는 데이터는 소멸될 수 있다. 그렇다면 TCP는 어떠한 원리로 중간에 소멸되는 데이터의 전송까지 보장을 하는 것인지 ACK와 SEQ를 대상으로 설명해보자.


>SEQ는 메세지에 번호를 부여하는데 사용된다. 반면 ACK는 번호가 부여된 메세지의 응답에 사용된다. 즉, 메세지를 보낼 때마다 SEQ 정보를 함께 보내는데, 이를 수신한 호스트는 이를 전송한 호스트에게 SEQ 정보를 바탕으로 ACK 메세지를 보내야 한다. 이러한 기본적인 형태로 데이터의 송수신을 확인하기 때문에 데이터를 전송한 호스트는 데이터의 전송여부를 확인할 수 있다. 따라서 데이터의 전송이 실패하는 경우에는 재전송을 진행할 수 있다.

 

*참고: TCP 소켓은 ACK 응답을 요구하는 패킷 전송 시에 타이머를 동작시키고 해당 타이머가 종료되었을 때 패킷을 재전송한다


3. TCP 소켓을 기반으로 write 함수와 read 함수가 호출되었을 때의 데이터 이동을 입력버퍼와 출력버퍼의 상태와 더불어서 설명해보자


>write 함수가 호출되는 순간 데이터는 소켓의 출력버퍼로 이동된다. 그리고 이동이 된 데이터는 TCP 프로토콜을 기반으로 상대방 호스트 소켓의 입력버퍼로 전송이 되며, 이렇게 해서 입력버퍼에 저장된 데이터는 read 함수의 호출을 통해서 읽혀진다.


4. 데이터를 수신할 상대 호스트의 입력버퍼에 남아있는 여유공간이 50byte인 상황에서 write 함수호출을 통해서 70byte의 데이터 전송을 요청했을 때, TCP는 어떻게 이를 처리하는지 설명해보자.


>수신할 상대 호스트의 입력버퍼에 저장 가능한 데이터 크기는 데이터를 전송하는 호스트에 전달된다. 따라서, 여유공간이 50byte인 상황에서는 70byte의 데이터의 전송이 요청되더라도, 50byte 이상이 전송되지 않는다. 나머지는 전송하는 호스트의 출력버퍼에 저장된 상태에서 상대 호스트의 입력버퍼에 여유가 생길 때까지 기다린다. 그리고 이렇게 버퍼의 여유공간 정보를 교환하는 프로토콜을 가리켜 슬라이딩 윈도우라고 하며,  이 역시 TCP 프로토콜의 일부이다.


5. 2장에서 보인 예제 tcp_server.c와 tcp_client.c에서는 서버가 전송하는 문자열을 클라이언트가 수신하고 끝낸다. 그런데 이번에는 서버와 클라이언트가 한번씩 문자열을 주고받는 형태로 예제를 변경해보자.

(단, 데이터의 송수신이 TCP기반으로 진행된다는 사실을 고려하여 문자열 전송에 앞서 문자열의 길이 정보를 4바이트 정수의 형태로 먼저 전송하기로 하자.)


>리눅스 서버 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/types.h>

#include <sys/socket.h>

 

void error_handling(char *message);

 

int main(int argc, char *argv[])

{

        int serv_sock;

        int clnt_sock;

        int str_len, i;

 

        struct sockaddr_in serv_addr;

        struct sockaddr_in clnt_addr;

        socklen_t clnt_addr_size;

 

        char message1[] = "Hello Client!";

        char message2[] = "I like";

        char message3[] = "gudetama";

        char* str_arr[] = { message1, message2, message3 };

        char read_buf[100];

 

        if (argc != 2) {

               printf("Usage : %s <port>\n", argv[0]);

               exit(1);

        }

 

        serv_sock = socket(PF_INET, SOCK_STREAM, 0); //socket 함수호출을 통해서 소켓을 생성

        if (serv_sock == -1)

               error_handling("socket() error");

 

        memset(&serv_addr, 0, sizeof(serv_addr));

        serv_addr.sin_family = AF_INET;

        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

        serv_addr.sin_port = htons(atoi(argv[1]));

 

        if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)//bind 함수호출을 통해서 IP주소와 PORT번호를 할당

               error_handling("bind() error");

 

        if (listen(serv_sock, 5) == -1)//listen 함수를 호출, 이로써 소켓은 연결요청을 받아들일 있는 상태

               error_handling("listen() error");

 

        clnt_addr_size = sizeof(clnt_addr);

        clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);//연결요청의 수락을 위한 accept함수 호출

                                                                                                                                                        //연결요청이 없는 상태에서 이함수가 호출되면, 연결요청이 있을 때까지 함수는 반환하지 않는다

        if (clnt_sock == -1)

               error_handling("accept() error");

 

        for (i = 0; i<3; i++)

        {

               str_len = strlen(str_arr[i]) + 1;

               write(clnt_sock, (char*)(&str_len), 4); //문자열의 길이 정보를 4바이트 정수의 형태로 먼저 전송

               write(clnt_sock, str_arr[i], str_len); //문자열을 전송

 

               read(clnt_sock, (char*)(&str_len), 4); //문자열의 길이 정보 4바이트 정수의 형태로 수신

               read(clnt_sock, read_buf, str_len); //문자열을 수신

               puts(read_buf);

        }

 

        close(clnt_sock);

        close(serv_sock);

        return 0;

}

 

void error_handling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

 

언제나처럼 정상적으로 실행되면 화면이 멈추고 커서만 깜빡인다.


리눅스 클라이언트 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/types.h>

#include <sys/socket.h>

 

void error_handling(char *message);

 

int main(int argc, char* argv[])

{

        int sock;

        struct sockaddr_in serv_addr;

 

        char message1[] = "Hello Server!";

        char message2[] = "I like";

        char message3[] = "gudetama, too";

        char* str_arr[] = { message1, message2, message3 };

        char read_buf[100];

 

        int str_len, i;

 

        if (argc != 3) {

               printf("Usage : %s <IP> <port>\n", argv[0]);

               exit(1);

        }

 

        sock = socket(PF_INET, SOCK_STREAM, 0); //소켓을 생성

        //소켓을 생성하는 순간에는 서버 소켓과 클라이언트 소켓으로 나누어지지 않는다.

        //bind, listen 함수의 호출이 이어지면 서버 소켓이 되는 것이고, connect 함수의 호출로 이어지면 클라이언트 소켓이 되는 것이다

        if (sock == -1)

               error_handling("socket() error");

 

        memset(&serv_addr, 0, sizeof(serv_addr));

        serv_addr.sin_family = AF_INET;

        serv_addr.sin_addr.s_addr = inet_addr(argv[1]);

        serv_addr.sin_port = htons(atoi(argv[2]));

 

        if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)//connect 함수호출을 통해서 서버프로그램에 연결을 요청

               error_handling("connect() error!");

 

        for (i = 0; i<3; i++)

        {

               read(sock, (char*)(&str_len), 4); //문자열의 길이 정보를 4바이트 형태로 읽어들인다

               read(sock, read_buf, str_len); //문자열을 읽어들인다

               puts(read_buf);

 

               str_len = strlen(str_arr[i]) + 1;

               write(sock, (char*)(&str_len), 4); //문자열의 길이 정보를 4바이트 형태로 전송한다

               write(sock, str_arr[i], str_len); //문자열을 전송한다

        }

        close(sock);

        return 0;

}

 

void error_handling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

 

클라이언트 프로그램이 정상적으로 실행이된다면 서버측에서 보낸 메세지를 확인할 수 있다.

또한 서버 프로그램을 실행한 창에 가보면 클라이언트측에서도 메세지를 보낸 것을 확인할 수 있다


윈도우 서버 프로그램

#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;

        int str_len, i;

 

        char message1[] = "Hello Client!";

        char message2[] = "I like";

        char message3[] = "gudetama";

        char *str_arr[] = { message1, message2, message3 };

        char read_buf[100];

 

        if (argc != 2)

        {

               printf("Usage:%s <port>\n", argv[0]);

               exit(1);

        }

 

        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) //소켓에 IP주소와 PORT 번호 할당

               ErrorHandling("bind() error");

 

        if (listen(hServSock, 5) == SOCKET_ERROR) //listen 함수호출을 통해서 생성한 소켓을 서버 소켓으로 완성

               ErrorHandling("listen() error");

 

        szClntAddr = sizeof(clntAddr);

        hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr); //클라이언트 연결요청 수락하기 위해 accept함수 호출

        if (hClntSock == INVALID_SOCKET)

               ErrorHandling("accept() error");

 

        for (i = 0; i < 3; i++)

        {

               str_len = strlen(str_arr[i]) + 1;

               send(hClntSock, (char*)(&str_len), 4, 0); //문자열의 길이 정보를 4바이트 정수의 형태로 먼저 전송

               send(hClntSock, str_arr[i], str_len, 0); //문자열을 전송

 

               recv(hClntSock, (char*)(&str_len), 4, 0); //문자열의 길이 정보 4바이트 정수의 형태로 수신

               recv(hClntSock, read_buf, str_len, 0); //문자열을 수신

               puts(read_buf);

        }

        closesocket(hClntSock);

        closesocket(hServSock);

        WSACleanup(); //프로그램 종료 전에 초기화한 소켓 라이브러리 해제

        return 0;

}

 

void ErrorHandling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

 

마찬가지로 정상적으로 실행되면 cmd창이 멈추고 커서만 깜빡인다


윈도우 클라이언트 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <WinSock2.h>

 

void ErrorHandling(char *message);

 

int main(int argc, char *argv[])

{

        WSADATA wsaData;

        SOCKET hSocket; //socket 함수의 반환 저장을 위해서 SOCKET 변수 하나를 선언

        SOCKADDR_IN servAddr;

 

        char message1[]="Hello Server!";

        char message2[] = "I like";

        char message3[] = "gudetama, too";

        char *str_arr[] = { message1, message2, message3 };

        char read_buf[100];

        int str_len, i;

 

        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); //socket 함수호출을 통해서 TCP소켓을 생성

        if (hSocket == INVALID_SOCKET)

               ErrorHandling("hSocket() 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)//connect 함수호출을 통해서 서버프로그램에 연결을 요청

               ErrorHandling("connect() error!");

 

        for (i = 0; i<3; i++)

        {

               recv(hSocket, (char*)(&str_len), 4, 0); //문자열의 길이 정보를 4바이트 형태로 읽어들인다

               recv(hSocket, read_buf, str_len, 0); //문자열을 읽어들인다

               puts(read_buf);

 

               str_len = strlen(str_arr[i]) + 1;

               send(hSocket, (char*)(&str_len), 4, 0); //문자열의 길이 정보를 4바이트 형태로 전송한다

               send(hSocket, str_arr[i], str_len, 0); //문자열을 전송한다

        }

       

 

        closesocket(hSocket);

        WSACleanup();

        return 0;

}

 

void ErrorHandling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

서버로부터 받은 메세지를 확인할 수 있다


또한 서버 cmd로 넘어가면 클라이언트로부터 받은 메세지를 확인 할 수 있다.


6. 파일을 송수신하기 위한 클라이언트와 서버를 구현하되, 다음 순서의 시나리오를 기준으로 구현해보자

   a.클라이언트는 프로그램 사용자로부터 전송 받을 파일의 이름을 입력 받는다

   b.클라이언트는 해당 이름의 파일전송을 서버에게 요청한다

   c.파일이 존재할 경우 서버는 파일을 전송하고, 파일이 존재하지 않을 경우 그냥 연결을 종료한다


>리눅스 서버 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>

 

#define BUF_SIZE 30

void error_handling(char *message);

 

int main(int argc, char *argv[])

{

        int serv_sd, clnt_sd;

        FILE * fp;

        char buf[BUF_SIZE];

        char file_name[BUF_SIZE];

        int read_cnt;

 

        struct sockaddr_in serv_adr, clnt_adr;

        socklen_t clnt_adr_sz;

 

        if (argc != 2) 

{

               printf("Usage: %s <port>\n", argv[0]);

               exit(1);

        }

 

        serv_sd = socket(PF_INET, SOCK_STREAM, 0);//socket 함수호출을 통해서 소켓을 생성

 

        memset(&serv_adr, 0, sizeof(serv_adr));

        serv_adr.sin_family = AF_INET;

        serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);

        serv_adr.sin_port = htons(atoi(argv[1]));

 

        bind(serv_sd, (struct sockaddr*)&serv_adr, sizeof(serv_adr));//bind 함수호출을 통해서 IP주소와 PORT번호를 할당

        listen(serv_sd, 5);//listen 함수를 호출, 이로써 소켓은 연결요청을 받아들일 있는 상태

 

        clnt_adr_sz = sizeof(clnt_adr);

        clnt_sd = accept(serv_sd, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); // 연결요청의 수락을 위한 accept함수 호출

               //연결요청이 없는 상태에서 이함수가 호출되면, 연결요청이 있을 때까지 함수는 반환하지 않는다

 

        read(clnt_sd, file_name, BUF_SIZE); //클라이언트로부터 파일의 이름을 수신받는다

        fp = fopen(file_name, "rb"); //파일을 열고

        if (fp != NULL) //파일이 존재할경우

        {

               while (1) //서버는 파일을 전송한다

               {

                       read_cnt = fread((void*)buf, 1, BUF_SIZE, fp);

                       if (read_cnt<BUF_SIZE)

                       {

                              write(clnt_sd, buf, read_cnt);

                              break;

                       }

                       write(clnt_sd, buf, BUF_SIZE);

               }

        }

 

        fclose(fp);

        close(clnt_sd);

        close(serv_sd);

        return 0;

}

 

void error_handling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

 

정상적으로 실행되면 창이 멈추고 커서만 깜빡인다


리눅스 클라이언트 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>

 

#define BUF_SIZE 30

void error_handling(char *message);

 

int main(int argc, char *argv[])

{

        int sd;

        FILE *fp;

 

        char buf[BUF_SIZE];

        char file_name[BUF_SIZE];

        int read_cnt;

        struct sockaddr_in serv_adr;

        if (argc != 3)

        {

               printf("Usage: %s <IP> <port>\n", argv[0]);

               exit(1);

        }

 

        printf("Input file name: "); //전송 받을 파일의 이름을 입력받는다

        scanf("%s", file_name);

        fp = fopen(file_name, "wb");

 

        sd = socket(PF_INET, SOCK_STREAM, 0);//소켓을 생성

        //소켓을 생성하는 순간에는 서버 소켓과 클라이언트 소켓으로 나누어지지 않는다.

        //bind, listen 함수의 호출이 이어지면 서버 소켓이 되는 것이고, connect 함수의 호출로 이어지면 클라이언트 소켓이 되는 것이다

        memset(&serv_adr, 0, sizeof(serv_adr));

        serv_adr.sin_family = AF_INET;

        serv_adr.sin_addr.s_addr = inet_addr(argv[1]);

        serv_adr.sin_port = htons(atoi(argv[2]));

 

        connect(sd, (struct sockaddr*)&serv_adr, sizeof(serv_adr));//connect 함수호출을 통해서 서버프로그램에 연결을 요청

        write(sd, file_name, strlen(file_name) + 1); //파일전송을 서버에게 요청

 

        while ((read_cnt = read(sd, buf, BUF_SIZE)) != 0) //파일이 존재할 경우 전송을 받는다

               fwrite((void*)buf, 1, read_cnt, fp);

 

        fclose(fp);

        close(sd);

        return 0;

}

 

void error_handling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

 

동일한 컴퓨터에서 파일을 전송받는 것이기 때문에 과정을 눈으로 확인할 수는 없다.


윈도우 서버 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <WinSock2.h>

 

#define BUF_SIZE 30

 

void ErrorHandling(char *message);

 

int main(int argc, char *argv[])

{

        WSADATA wsaData;

        SOCKET hServSock, hClntSock;

        SOCKADDR_IN servAddr, clntAddr;

        FILE *fp;

        char buf[BUF_SIZE];

        char file_name[BUF_SIZE];

        int read_cnt;

 

        int szClntAddr;

        if (argc != 2)

        {

               printf("Usage:%s <port>\n", argv[0]);

               exit(1);

        }

 

        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) //소켓에 IP주소와 PORT 번호 할당

               ErrorHandling("bind() error");

 

        if (listen(hServSock, 5) == SOCKET_ERROR) //listen 함수호출을 통해서 생성한 소켓을 서버 소켓으로 완성

               ErrorHandling("listen() error");

 

        szClntAddr = sizeof(clntAddr);

        hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr); //클라이언트 연결요청 수락하기 위해 accept함수 호출

        if (hClntSock == INVALID_SOCKET)

               ErrorHandling("accept() error");

 

        recv(hClntSock, file_name, BUF_SIZE, 0); //클라이언트로부터 파일의 이름을 수신받는다

        fp = fopen(file_name, "rb"); //파일을 열고

        if (fp != NULL) //파일이 존재할경우

        {

               while (1) //서버는 파일을 전송한다

               {

                       read_cnt = fread((void*)buf, 1, BUF_SIZE, fp);

                       if (read_cnt<BUF_SIZE)

                       {

                              send(hClntSock, buf, read_cnt, 0);

                              break;

                       }

                       send(hClntSock, buf, BUF_SIZE, 0);

               }

        }

 

        fclose(fp);

        closesocket(hClntSock);

        closesocket(hServSock);

        WSACleanup(); //프로그램 종료 전에 초기화한 소켓 라이브러리 해제

        return 0;

}

 

void ErrorHandling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

 


정상적으로 실행되면 cmd창이 멈추고 커서만 깜빡인다


윈도우 클라이언트 프로그램

#include <stdio.h>

#include <stdlib.h>

#include <WinSock2.h>

 

#define BUF_SIZE 30

 

void ErrorHandling(char *message);

 

int main(int argc, char *argv[])

{

        WSADATA wsaData;

        SOCKET hSocket; //socket 함수의 반환 저장을 위해서 SOCKET 변수 하나를 선언

        SOCKADDR_IN servAddr;

 

        FILE *fp;

        char buf[BUF_SIZE];

        char file_name[BUF_SIZE];

        int read_cnt = 0;

 

        if (argc != 3)

        {

               printf("Usage:%s <IP> <port>\n", argv[0]);

               exit(1);

        }

 

        printf("Input file name: "); //전송 받을 파일의 이름을 입력받는다

        scanf("%s", file_name);

        fp = fopen(file_name, "wb");

 

        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)

               ErrorHandling("WSAStartup() error!");

 

        hSocket = socket(PF_INET, SOCK_STREAM, 0); //socket 함수호출을 통해서 TCP소켓을 생성

        if (hSocket == INVALID_SOCKET)

               ErrorHandling("hSocket() 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!");

 

        send(hSocket, file_name, strlen(file_name) + 1, 0);//파일전송을 서버에게 요청

 

        while ((read_cnt = recv(hSocket, buf, BUF_SIZE, 0)) != 0)//파일이 존재할 경우 전송을 받는다

               fwrite((void*)buf, 1, read_cnt, fp);

 

        fclose(fp);

        closesocket(hSocket);

        WSACleanup();

        return 0;

}

 

void ErrorHandling(char *message)

{

        fputs(message, stderr);

        fputc('\n', stderr);

        exit(1);

}

동일한 컴퓨터에서 파일을 전송받는 것이기 때문에 과정을 눈으로 확인할 수는 없다.



[참고] TCP/IP 소켓 프로그래밍 윤성우 저

반응형