ABOUT ME

Today
Yesterday
Total
  • [열혈 TCP/IP 소켓 프로그래밍] Chapter2. 내용 확인문제
    Study/Network 2022. 9. 19. 19:50

    01. 프로토콜이 무엇인가?

    • 프로토콜이란, 데이터의 전송 방식을 결정하는 규약이다.
    • 두 컴퓨터 간 프로토콜을 정의해야 데이터 전송 방식을 서로 알고 해석할 수 있다.

    02. 연결지향 소켓 TCP의 전송 특성 3가지

    • 데이터의 손실이 없음이 보장된다.
    • 데이터의 경계가 없다
    • 데이터의 전송 순서가 보장된다.

    03. 비연결지향 소켓 UDP의 전송 특성

    • 데이터의 손실이 있을 수 있다.
    • 빠른 전송을 목표로 한다.
    • 한 번의 전송에 데이터의 크기가 제한된다.
    • 연결이라는 개념이 존재하지 않는다.

    04. 유형별 적합한 타입의 소켓은?

    • 실시간 스트리밍 : UDP 소켓. 빠른 전송이 목표가 되어야 하고, 데이터가 손실되더라도 최신의 데이터를 계속 받는 것이 더 중요하다.
    • 텍스트 파일 전송 : TCP 소켓. 순서가 무조건 보장되어야 하고 데이터의 손실이 없어야 한다.
    • 인터넷 뱅킹 : 데이터의 손실이 절대 있어서는 안 된다.

    05. 데이터의 경계가 존재하지 않는 소켓은? 그리고 이러한 소켓을 통해 데이터를 수신할 때 주의점

    • 데이터의 경계가 존재하지 않는 소켓은 TCP 소켓이다.
    • 수신할 때 주의할 점은, 소켓 내부의 버퍼에 데이터가 저장되고, read 함수 호출을 통해 버퍼에 있는 데이터를 비우는 방식이기 때문에 버퍼가 가득 차게 된다면 더 이상 데이터를 수신할 수 없다.
    • 데이터가 손실되지는 않지만 데이터를 더 이상 받을 수 없기 때문에 주의해야 한다.

    06. 서버에서 데이터를 쪼개서 보내보기

    서버 코드

    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <WinSock2.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    void ErrorHandling(char* Message);
    
    int main(int argc, char* argv[])
    {
    	WSADATA wsaData;
    	SOCKET hServerSock, hClntSock;
    	SOCKADDR_IN servAddr, clntAddr;
    
    	int szClntAddr;
    	char message[] = "Hello World!";
    
    	if (argc != 2)
    	{
    		printf("Usage %s <port>\n", argv[0]);
    		exit(1);
    	}
    
    	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    	{
    		ErrorHandling("WSAStartUp() error");
    	}
    
    	hServerSock = socket(PF_INET, SOCK_STREAM, 0);
    	if (hServerSock == 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(hServerSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
    	{
    		ErrorHandling("bind() error");
    	}
    
    	if (listen(hServerSock, 5) == SOCKET_ERROR)
    	{
    		ErrorHandling("listen() error");
    	}
    
    	szClntAddr = sizeof(clntAddr);
    	hClntSock = accept(hServerSock, (SOCKADDR*)&clntAddr, &szClntAddr);
    
    	if (hClntSock == INVALID_SOCKET)
    	{
    		ErrorHandling("accept() error");
    	}
    
    	int len = strlen(message);
    
    	for (int i = 0; i < len; ++i)
    	{
    		send(hClntSock, &message[i], sizeof(char), 0);
    	}
    
    	closesocket(hClntSock);
    	closesocket(hServerSock);
    	WSACleanup();
    }
    
    void ErrorHandling(char* Message)
    {
    	fputs(Message, stderr);
    	fputc('\n', stderr);
    	exit(1);
    }

     

    클라이언트 코드

    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <WinSock2.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    void ErrorHandling(char* Message);
    
    int main(int argc, char* argv[])
    {
    	WSADATA wsaData;
    	SOCKET hSocket;
    	SOCKADDR_IN servAddr;
    
    	char message[30];
    
    	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");
    	}
    
    	// busy - waiting
    	for (int i = 0; i < 3000; ++i)
    	{
    		printf("Wait Time : %d\n", i);
    	}
    
    	recv(hSocket, message, 12, 0);
        message[12] = '\0';
    
    	printf("Message From Server : %s", message);
    
    	closesocket(hSocket);
    	WSACleanup();
    
    	return 0;
    }
    
    void ErrorHandling(char* Message)
    {
    	fputs(Message, stderr);
    	fputc('\n', stderr);
    	exit(1);
    }

    댓글

GameDev.