본문 바로가기
게임 개발/C++

OS 무관 채팅 프로그램 만들기 - 2 : ChatGPT 이용한 서버-클라이언트 채팅 프로그램 짜기

 

내가 TCP 소켓프로그래밍을 공부한 교재에서는 파이썬으로 다루었기 때문에

C++로 TCP Server-Client Chatting 프로그램을 새로 짜야했다.

 

이것에 딱 적합한 요즘 핫이슈가 있지 그래.

챗GPT한테 짜달라고 해보자.

 

 

 

 

나 : C++로 TCP 채팅 시스템의 서버 코드를 만들어줘. 

챗GPT : 그래, C++로 TCP 채팅 서버 시스템의 기본적인 실행을 줄게. 여기 예시야~

 

 

 

 

그렇게 준 코드 ⬇️

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <vector>

using namespace std;

vector<int> client_sockets;

void *client_handler(void *arg)
{
    int client_socket = *(int *)arg;
    char message[256];

    while (true)
    {
        memset(message, 0, sizeof(message));
        int bytes_read = read(client_socket, message, sizeof(message));
        if (bytes_read <= 0)
        {
            close(client_socket);
            pthread_exit(NULL);
        }

        cout << message << endl;

        for (int i = 0; i < client_sockets.size(); i++)
        {
            if (client_sockets[i] != client_socket)
            {
                write(client_sockets[i], message, strlen(message));
            }
        }
    }
}

int main()
{
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0)
    {
        cout << "Error creating socket" << endl;
        return -1;
    }

    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(12345);
    server_address.sin_addr.s_addr = INADDR_ANY;

    if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) < 0)
    {
        cout << "Error binding socket" << endl;
        return -1;
    }

    listen(server_socket, 5);

    while (true)
    {
        struct sockaddr_in client_address;
        socklen_t client_address_size = sizeof(client_address);
        int client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_address_size);

        if (client_socket < 0)
        {
            cout << "Error accepting client connection" << endl;
            continue;
        }

        cout << "Client connected: " << inet_ntoa(client_address.sin_addr) << endl;

        pthread_t thread_id;
        int *client_socket_ptr = new int;
        *client_socket_ptr = client_socket;
        client_sockets.push_back(client_socket);
        pthread_create(&thread_id, NULL, client_handler, (void *)client_socket_ptr);
    }

    close(server_socket);
    return 0;
}

 

챗GPT : 이 예시의 경우 서버 소켓을 만들고, 그걸 포트에 바인딩하고, 연결 신호를 듣게 만들었어.

클라이언트가 연결을 시도할 때, 클라이언트의 메시지를 다루는 새로운 스레드를 만들게 했어.

 

client_handler 함수는 클라이언트 소켓으로부터 메시지를 읽어들이고, 그걸 연결된 다른 모든 클라이언트들에게로 브로드캐스팅(전송)해. 클라이언트가 연결되지 않았을 때 스레드는 종료돼.

 

이건 단지 기본적인 예시이고 에러 처리나 인증은 되어있지 않아. 현실에서의 응용하려면 암호화, 사용자 인증, 에러 처리 같은 기능들을 추가하는 게 좋을거야.

 

라고 하네요 Wow~ 친절하다 (나는 뭐해먹고 살지요?)

 

 

다음은 클라이언트 코드

 

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>

using namespace std;

int main() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        cerr << "Could not create socket" << endl;
        return 1;
    }
    
    sockaddr_in server;
    server.sin_addr.s_addr = inet_addr("127.0.0.1"); // change to your server IP address
    server.sin_family = AF_INET;
    server.sin_port = htons(8888); // change to your desired port number
    
    if (connect(sock, (sockaddr*)&server, sizeof(server)) < 0) {
        cerr << "Connection error" << endl;
        return 1;
    }
    
    char message[2000];
    while (true) {
        cout << "Enter message: ";
        cin.getline(message, 2000);
        
        if (send(sock, message, strlen(message), 0) < 0) {
            cerr << "Send failed" << endl;
            return 1;
        }
        
        memset(message, 0, sizeof(message));
        
        if (recv(sock, message, 2000, 0) < 0) {
            cerr << "Receive failed" << endl;
            break;
        }
        
        cout << "Server reply: " << message << endl;
    }
    
    close(sock);
    
    return 0;
}

 

socket() : 소켓 생성 함수

sockaddr_in : 연결할 서버 주소

connect() : 서버에 연걸하는 함수

send() 와 recv() : 메시지를 주고받는 함수

 

이건 서버와 메시지만 주고 받을 수 있을 뿐인 코드니까 채팅 시스템을 만들고 싶다면 서버와 클라이언트 사이에 2방향 소통이 가능한 코드로 수정하도록 해.

 

 

아무래도 서버랑 따로 물어봐서 둘의 연결은 내가 해야할 성 싶다.