티스토리 뷰

책 ) 뇌를 자극하는 TCP/IP 소켓 프로그래밍

 

코드는 두가지로 Server 코드와 Client 코드 두개로 나뉘어집니다.

책을 공부하면서 원래는 기본적인 Socket 통신은 알고 있었지만, 구조체를 통해서도 데이터를 전달할 수 있다는 것을 알게 되었습니다.

따라서 소켓 프로그래밍을 할때 어떤 방식으로 구조체 데이터를 넘기는지 확인하시면 될 것 같습니다.

 

// DoummyClient
#pragma warning(disable:4996)

#include<stdio.h>
#include<iostream>
#include<Winsock2.h>
#pragma comment(lib, "ws2_32.lib")

#define PORT	3600
#define IP		"127.0.0.1"

void HandleError(const char* cause) {
	int errCode = ::WSAGetLastError();
	std::cout << cause << "Error Code : " << errCode << std::endl;
}

struct cal_data {  //전달할 구조체
	int left_num;
	int right_num;
	char op;
	int result;
	short int error;
};

int main() {
	SOCKADDR_IN addr;
	SOCKET s;
	WSADATA wsaData;
	char buffer[256];
	int len;
	int sbyte, rbyte;
	struct cal_data sdata;
	
	ZeroMemory((void*)&sdata, sizeof(sdata));
	sdata.left_num = 100;
	sdata.right_num = 50;
	sdata.op = '+';

	if (::WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
		HandleError("WSAStartup");

	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s == INVALID_SOCKET)
		HandleError("socket");

	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr = inet_addr(IP);
	addr.sin_port = ::htons(PORT);

	if (::connect(s, (const sockaddr*)&addr, sizeof(addr)) == INVALID_SOCKET)
		HandleError("connet");

	len = sizeof(sdata);
	sdata.left_num = htonl(sdata.left_num);		//넘겨줄 데이터 저장 시 
	sdata.right_num = htonl(sdata.right_num);	//네트워크 바이트 주소로 변경
	sbyte = ::send(s, (char*)&sdata, len, 0);   //char* 형태로 형변환 후 전달
	if (sbyte != len) 
		HandleError("Send");
	
	rbyte = recv(s, (char*)&sdata, len, 0);		//데이터 전달 받음
	if (rbyte != len)
		HandleError("Recv");

	if (ntohs(sdata.error != 0))				//네트워크 바이트를 호스트 바이트형식으로 변경
		printf("CALC Error %d\n", ntohs(sdata.error));

	printf("%d %c %d = %d \n", ntohl(sdata.left_num), // 출력
		ntohl(sdata.op), ntohl(sdata.right_num), ntohl(sdata.result));

	::closesocket(s);
	WSACleanup();
}

//DummyServer
#pragma warning(disable:4996)

#include<stdio.h>
#include<iostream>
#include<Winsock2.h>
#include<string.h>
#include<io.h>

#pragma comment(lib, "ws2_32.lib")
#define PORT	3600

void HandleError(const char* cause) {
	int errCode = ::WSAGetLastError();
	std::cout << cause << "Error Code : " << errCode << std::endl;
}

struct cal_data {
    int left_num;
    int right_num;
    char op;
    int result;
    short int error;
};

int main()
{
    WSADATA wsaData;
    SOCKET listen_s, client_s;
    SOCKADDR_IN sock_addr, client_addr;
    int addr_len;
    int left_num, right_num;
    short int cal_result;
    struct cal_data rdata;
    
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        HandleError("WSAStartup");

    listen_s = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_s == INVALID_SOCKET)
        HandleError("socket");

    ZeroMemory(&sock_addr, sizeof(struct sockaddr_in));

    sock_addr.sin_family = PF_INET;
    sock_addr.sin_port = htons(PORT);
    sock_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    if (bind(listen_s, (struct sockaddr*)&sock_addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
    {
        HandleError("Bind");
        return 1;
    }
    if (listen(listen_s, 5) == SOCKET_ERROR)
    {
        HandleError("listen");
        return 1;
    } 

    ZeroMemory(&client_addr, sizeof(struct sockaddr_in));

    int nAcceptClientInfo = sizeof(struct sockaddr_in);
    client_s = accept(listen_s, (struct sockaddr*)&client_addr, &nAcceptClientInfo);
    int nReceiveBytes = 0;
    printf("New Client Connected : %s\n", inet_ntoa(client_addr.sin_addr));

    while (1)
    {
        recv(client_s, (char*)&rdata, sizeof(rdata), 0);
        rdata.error = 0;
        left_num = ntohl(rdata.left_num);
        right_num = ntohl(rdata.right_num);

        switch (rdata.op) {
        case '+':
            cal_result = left_num + right_num;
            break;
        case '-':
            cal_result = left_num - right_num;
            break;
        case '*':
            cal_result = left_num * right_num;
            break;
        case '/':
            cal_result = left_num / right_num;
            break;
        default:
            rdata.error = 1;
        }
        std::cout << "cal_result : " << cal_result << std::endl;
        rdata.result = htonl(cal_result);
        rdata.error = htonl(cal_result);

        send(client_s, (char*)&rdata, sizeof(rdata), 0);
        break;
    }

    closesocket(listen_s);
    WSACleanup();
    return 0;
}
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함