Metin2-like socket communication ex. (serverside)

isthambul1453

Premium Üye
Premium Üye
Üye
Mesaj
78
Beğeni
54
Puan
331
Ticaret Puanı
0
Bu tarz basit bir sunucu-istemci iletişimi (socket communication) ile pek çok uygulama geliştirilebilir. (Hastane, kütüphane, vsvs.) Bu mevcut kod yapısı, yalnızca bağlantı kurulumu ve doğrulama işlemlerini gösterdiği için çok temel düzeyde kalmaktadır ve gerçek bir uygulama gibi kullanılabilmesi için kod yapısının geliştirilmesi gerekmektedir.

1753011673968.webp


SimpleServer:
Genişlet Daralt Kopyala
CXX=g++
CXXFLAGS=- std=c++11 -Wall -O2

all: simple_server

simple_server: simple_server.o
    $(CXX) $(CXXFLAGS) -o simple_server simple_server.o

simple_server.o: simple_server.cpp packet.h
    $(CXX) $(CXXFLAGS) -c simple_server.cpp

clean:
    rm -f simple_server.o simple_server

.PHONY: all clean

packet.h:
Genişlet Daralt Kopyala
#ifndef METIN2_SIMPLE_PACKET_H
#define METIN2_SIMPLE_PACKET_H

#include <cstdint>

enum PacketHeader : uint8_t {
    HEADER_CG_HANDSHAKE = 0xff,
    HEADER_GC_HANDSHAKE = 0xff
};

#pragma pack(push, 1)
struct TPacketCGHandshake {
    uint8_t  bHeader;
    uint32_t dwHandshake;
    uint32_t dwTime;
    int32_t  lDelta;
};

struct TPacketGCHandshake {
    uint8_t  bHeader;
    uint32_t dwHandshake;
    uint32_t dwTime;
    int32_t  lDelta;
};
#pragma pack(pop)

#endif // METIN2_SIMPLE_PACKET_H

simple_server.cpp:
Genişlet Daralt Kopyala
#include "packet.h"
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <ctime>
#include <cstring>

uint32_t get_dword_time() {
    return static_cast<uint32_t>(time(nullptr));
}

int main() {
    srand(static_cast<unsigned int>(time(nullptr)));

    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket");
        return 1;
    }

    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(13000);

    if (bind(server_fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
        perror("bind");
        return 1;
    }

    if (listen(server_fd, 5) == -1) {
        perror("listen");
        return 1;
    }

    std::cout << "Simple server started on port 13000\n";

    while (true) {
        sockaddr_in client_addr{};
        socklen_t client_len = sizeof(client_addr);
        int client_fd = accept(server_fd, reinterpret_cast<sockaddr*>(&client_addr), &client_len);
        if (client_fd == -1) {
            perror("accept");
            continue;
        }

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

        uint32_t handshake = static_cast<uint32_t>(rand());
        TPacketGCHandshake out_packet{};
        out_packet.bHeader = HEADER_GC_HANDSHAKE;
        out_packet.dwHandshake = handshake;
        out_packet.dwTime = get_dword_time();
        out_packet.lDelta = 0;

        if (send(client_fd, &out_packet, sizeof(out_packet), 0) != sizeof(out_packet)) {
            std::cerr << "Failed to send handshake" << std::endl;
            close(client_fd);
            continue;
        }

        TPacketCGHandshake in_packet{};
        ssize_t received = recv(client_fd, &in_packet, sizeof(in_packet), 0);
        if (received != sizeof(in_packet)) {
            std::cerr << "Invalid handshake size" << std::endl;
            close(client_fd);
            continue;
        }

        if (in_packet.bHeader != HEADER_CG_HANDSHAKE || in_packet.dwHandshake != handshake) {
            std::cerr << "Handshake mismatch" << std::endl;
            close(client_fd);
            continue;
        }

        std::cout << "Handshake successful" << std::endl;

        const char msg[] = "Welcome to the Metin2-like server!\n";
        send(client_fd, msg, sizeof(msg) - 1, 0);

        close(client_fd);
    }

    close(server_fd);
    return 0;
}

Mevcut handshake kısmı sadece başlangıçtır!
Uygulama mantığı, veri yönetimi, istemci arayüzü gibi birçok parça daha gereklidir!
JSON veya protobuf gibi daha gelişmiş veri yapıları da tercih edilebilir.
 
Geri
Üst