首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >像ENet这样的库,但是针对TCP的?

像ENet这样的库,但是针对TCP的?
EN

Stack Overflow用户
提问于 2012-05-09 09:40:15
回答 3查看 3.2K关注 0票数 6

我不打算使用boost::asio,它对我的需求来说太复杂了。

我正在建立一个游戏,是跨平台的,为桌面,iPhone和安卓。

我找到了一个名为ENet的库,它几乎就是我所需要的,但它使用的UDP似乎不支持加密和其他一些东西。考虑到游戏是事件驱动的纸牌游戏,TCP似乎是合适的选择。

但是,我找到的只有WINSOCK / berkley套接字和bost::asio。

下面是一个使用ENet的示例客户端服务器应用程序:

代码语言:javascript
复制
#include <enet/enet.h>
#include <stdlib.h>
#include <string>
#include <iostream>

class Host
{
    ENetAddress address;
    ENetHost * server;
    ENetHost* client;
    ENetEvent event;
public:
    Host()
        :server(NULL)
    {
        enet_initialize();
        setupServer();
    }

    void setupServer()
    {
        if(server)
        {
            enet_host_destroy(server);
            server = NULL;
        }

        address.host = ENET_HOST_ANY;
        /* Bind the server to port 1234. */
        address.port = 1721;

        server = enet_host_create (& address /* the address to bind the server host to */, 
            32      /* allow up to 32 clients and/or outgoing connections */,
            2      /* allow up to 2 channels to be used, 0 and 1 */,
            0      /* assume any amount of incoming bandwidth */,
            0      /* assume any amount of outgoing bandwidth */);

    }

     void daLoop()
     {
         while(true)
         {
             /* Wait up to 1000 milliseconds for an event. */
             while (enet_host_service (server, & event, 5000) > 0)
             {
                 ENetPacket * packet;

                 switch (event.type)
                 {
                 case ENET_EVENT_TYPE_CONNECT:
                     printf ("A new client connected from %x:%u.\n", 
                         event.peer -> address.host,
                         event.peer -> address.port);

                     /* Store any relevant client information here. */
                     event.peer -> data = "Client information";

                     /* Create a reliable packet of size 7 containing "packet\0" */
                     packet = enet_packet_create ("packet", 
                         strlen ("packet") + 1, 
                         ENET_PACKET_FLAG_RELIABLE);

                     /* Extend the packet so and append the string "foo", so it now */
                     /* contains "packetfoo\0"                                      */
                     enet_packet_resize (packet, strlen ("packetfoo") + 1);
                     strcpy ((char*)& packet -> data [strlen ("packet")], "foo");

                     /* Send the packet to the peer over channel id 0. */
                     /* One could also broadcast the packet by         */
                     /* enet_host_broadcast (host, 0, packet);         */
                     enet_peer_send (event.peer, 0, packet);
                     /* One could just use enet_host_service() instead. */
                     enet_host_flush (server);

                     break;

                 case ENET_EVENT_TYPE_RECEIVE:
                     printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
                         event.packet -> dataLength,
                         event.packet -> data,
                         event.peer -> data,
                         event.channelID);

                     /* Clean up the packet now that we're done using it. */
                     enet_packet_destroy (event.packet);

                     break;

                 case ENET_EVENT_TYPE_DISCONNECT:
                     printf ("%s disconected.\n", event.peer -> data);

                     /* Reset the peer's client information. */

                     event.peer -> data = NULL;
                 }
             }
         }

     }

        ~Host()
    {
        if(server)
        {
            enet_host_destroy(server);
            server = NULL;
        }

        atexit (enet_deinitialize);
    }
};

class Client
{
    ENetAddress address;
    ENetEvent event;
    ENetPeer *peer;
    ENetHost* client;
public:
    Client()
        :peer(NULL)
    {
        enet_initialize();
        setupPeer();
    }

    void setupPeer()
    {

        client = enet_host_create (NULL /* create a client host */,
            1 /* only allow 1 outgoing connection */,
            2 /* allow up 2 channels to be used, 0 and 1 */,
            57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
            14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);

        if (client == NULL)
        {
            fprintf (stderr, 
                "An error occurred while trying to create an ENet client host.\n");
            exit (EXIT_FAILURE);
        }

        /* Connect to some.server.net:1234. */
        enet_address_set_host (& address, "192.168.2.13");
        address.port = 1721;

        /* Initiate the connection, allocating the two channels 0 and 1. */
        peer = enet_host_connect (client, & address, 2, 0);    

        if (peer == NULL)
        {
            fprintf (stderr, 
                "No available peers for initiating an ENet connection.\n");
            exit (EXIT_FAILURE);
        }

        /* Wait up to 5 seconds for the connection attempt to succeed. */
        if (enet_host_service (client, & event, 20000) > 0 &&
            event.type == ENET_EVENT_TYPE_CONNECT)
        {
            std::cout << "Connection to some.server.net:1234 succeeded." << std::endl;
        }
        else
        {
            /* Either the 5 seconds are up or a disconnect event was */
            /* received. Reset the peer in the event the 5 seconds   */
            /* had run out without any significant event.            */
            enet_peer_reset (peer);

            puts ("Connection to some.server.net:1234 failed.");
        }
    }


    void daLoop()
    {
        ENetPacket* packet;

        /* Create a reliable packet of size 7 containing "packet\0" */
        packet = enet_packet_create ("backet", 
            strlen ("backet") + 1, 
            ENET_PACKET_FLAG_RELIABLE);

        /* Extend the packet so and append the string "foo", so it now */
        /* contains "packetfoo\0"                                      */
        enet_packet_resize (packet, strlen ("backetfoo") + 1);
        strcpy ((char*)& packet -> data [strlen ("backet")], "foo");

        /* Send the packet to the peer over channel id 0. */
        /* One could also broadcast the packet by         */
        /* enet_host_broadcast (host, 0, packet);         */
        enet_peer_send (event.peer, 0, packet);
        /* One could just use enet_host_service() instead. */
        enet_host_flush (client);

        while(true)
        {
            /* Wait up to 1000 milliseconds for an event. */
            while (enet_host_service (client, & event, 1000) > 0)
            {
                ENetPacket * packet;

                switch (event.type)
                {
                case ENET_EVENT_TYPE_RECEIVE:
                    printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
                        event.packet -> dataLength,
                        event.packet -> data,
                        event.peer -> data,
                        event.channelID);

                    /* Clean up the packet now that we're done using it. */
                    enet_packet_destroy (event.packet);

                    break;
                }
            }
        }
    }
    ~Client()
    {
        atexit (enet_deinitialize);
    }
};

int main()
{
    std::string a;
    std::cin >> a;
    if(a == "host")
    {
        Host host;
        host.daLoop();
    }
    else
    {
        Client c;
        c.daLoop();
    }

    return 0;
}

我看过一些套接字教程,它们看起来有点太低级了。

我只需要一些抽象的平台(例如,没有WINSOCKS),并有基本的能力,以保持跟踪连接的客户端,并向他们发送消息。

谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-06 03:19:28

一封迟到的回信,但也许会对别人有所帮助。

加密是一种高级功能。TCP和UDP本身都不支持加密。它们都是低级协议。实际上,我们可以说,与UDP相比,TCP是一个更高级别的协议,因为TCP包含了一些可能有用的高级功能。或者不使用,这取决于将在其中使用它的项目。

ENet是好的,因为它提供了两个世界的好处- TCP的可靠性和UDP的自由和轻量级。ENet内部只使用UDP而不使用TCP这一事实并没有错,因为ENet能够提供TCP所做的几乎所有事情,甚至更多。

如果您希望有加密,您将不得不添加它自己,无论您是选择TCP,UDP或ENet。因此,我建议您继续使用ENet,如果您对它感到满意,并且当您的游戏启动并运行时,您可以添加任何您想要的加密算法,只要您为客户端和服务器选择相同的算法。你可以选择一个第三方加密库,然后通过它传递你的网络数据包。ENet不关心通过它发送的是什么数据。

也许下面的文章会对ENet有所帮助:

Network Programming with ENet By Mike Diehl

还可以看看下面的Stackoverflow主题,它是关于小型网络数据包加密的:

Best practices for encrypting continuous/small UDP data

票数 6
EN

Stack Overflow用户

发布于 2013-05-06 05:20:15

I heard魔多有一个安全套接字层,可用于网络加密。

票数 0
EN

Stack Overflow用户

发布于 2017-02-21 05:35:34

clsocket是一个很棒的小TCP库,允许开源许可证,Windows,Mac OSX,Linux:

https://github.com/DFHack/clsocket

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10508797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档