RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 772207
Accepted
Никита Самоуков
Никита Самоуков
Asked:2020-01-18 09:25:09 +0000 UTC2020-01-18 09:25:09 +0000 UTC 2020-01-18 09:25:09 +0000 UTC

C++ UDP Win -> Linux

  • 772

我写了 2 个简单的 udp 类(通过削减一些服务器和客户端代码)。

#include "usefull.h"
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment (lib, "Ws2_32.lib")

class IADDR
{
public:
    sockaddr_in addr;
    IADDR()
    {
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
    }
    IADDR(string ip,int16_t port)
    {
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        char buff1[100];

        InetPton(AF_INET, ip.c_str(), &addr.sin_addr.s_addr);
        addr.sin_port = htons(port);
        //addr.sin_addr.s_addr = htonl(addr.sin_addr.s_addr);
    }


};

class UDP
{
public:
    UDP()
    {
        ok = 0;
        if (!is_st)
        {
            WSADATA w;
            int res = WSAStartup(MAKEWORD(2, 2), &w);
            if (res != 0)
            {
                return;
            }
            is_st = 1;
        }
    }
    ~UDP()
    {
        if (ok == 1)
        {
            closesocket(sock);
            ok = 0;
        }
    }
    void set(IADDR a)
    {
        if (ok == 1)
        {
            closesocket(sock);
            ok = 0;
        }
        if (is_st == 0)
            return;
        addr = a;

        sock = socket(AF_INET, SOCK_DGRAM, 0);
        u_long nMode = 1;
        if (ioctlsocket(sock, FIONBIO, &nMode) == SOCKET_ERROR)
        {
            closesocket(sock);
        }

        ok = 1;
    }
    void send(vector<byte> v)
    {
        send(&v[0], v.size());
    }
    void send(const byte* buff, uint32_t size)
    {
        if (ok == 0)
            return;
        int len = sizeof(addr.addr);
        sendto(sock, (char*)buff, size, 0, (sockaddr*)&addr.addr, len);
    }
    bool recv(vector<byte> &data)
    {
        if (ok == 0)
            return 0;
        data.resize(1024);

        sockaddr_in serverInfo;

        int fromlen = sizeof(addr.addr);
        uint len = recvfrom(sock, (char*)&data[0], 1024, 0, (sockaddr*)&serverInfo, &fromlen);
        if (len != SOCKET_ERROR)
        {
            data.resize(len);
            return 1;
        }
        else
        {
            data.resize(0);
            return 0;
        }
    }
private:
    int sock;
    IADDR addr;
    int ok;
    static int is_st;
    friend class UDPSERVER;
};


class UDPSERVER
{
public:

    UDPSERVER()
    {
        ok = 0;
        if (!UDP::is_st)
        {
            WSADATA w;
            int res = WSAStartup(MAKEWORD(2, 2), &w);
            if (res != 0)
            {
                return;
            }
            UDP::is_st = 1;
        }
    }
    ~UDPSERVER()
    {
        if (ok == 1)
        {
            closesocket(sock);
            ok = 0;
        }
    }
    void set(USHORT port)
    {
        if (UDP::is_st == 0)
            return;
        if (ok == 1)
        {
            closesocket(sock);
            ok = 0;
        }
        struct sockaddr_in sv_ip;
        sv_ip.sin_family = AF_INET;
        sv_ip.sin_port = htons(port);
        sv_ip.sin_addr.s_addr = INADDR_ANY;

        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock == INVALID_SOCKET)
        {
            return;
        }

        u_long nMode = 1;
        if (ioctlsocket(sock, FIONBIO, &nMode) == SOCKET_ERROR)
        {
            closesocket(sock);
            return;
        }
        if (bind(sock, (sockaddr*)&sv_ip, sizeof(sv_ip)) == SOCKET_ERROR)
        {
            closesocket(sock);
            return;
        }
        ok = 1;
    }
    void send(vector<byte> v, IADDR &a)
    {
        send(&v[0], v.size(), a);
    }
    void send(const byte* buff, uint32_t size, IADDR &a)
    {
        if (ok == 0)
            return;
        int fromlen = sizeof(a.addr);
        sendto(sock, (char*)buff, size, 0, (sockaddr*)&a.addr, fromlen);
    }
    bool recv(vector<byte> &data, IADDR &a)
    {
        if (ok == 0)
            return 0;
        data.resize(1024);


        int fromlen = sizeof(a.addr);
        int len = recvfrom(sock, (char*)&data[0], 1024, 0, (sockaddr*)&a.addr, &fromlen);
        if (len != SOCKET_ERROR)
        {
            data.resize(len);
            return 1;
        }
        else
        {
            data.resize(0);
            return 0;
        }
    }
private:
    SOCKET sock;
    IADDR addr;
    int ok;
};
int UDP::is_st = 0;

我对套接字一无所知。它似乎工作正常,但它会崩溃吗?并且有必要以某种方式将其转移到 Linux,但是如何?使用 boost 是不可接受的!(因为安装需要 2 小时,甚至不是 1 次)。也不应该使用 QT。他有执照。

Win 编译 VS 和 Linux QTCreator。

我什至没有尝试在 Linux 下编译。显然在Windows下。

c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Ternvein
    2020-01-18T14:14:48Z2020-01-18T14:14:48Z

    要将代码转换为 Linux,您需要将套接字系统调用更改为 POSIX。按顺序,您的第一个调用是将定义 IPv4 地址的字符串通过InetPton. 它需要替换为以下内容:

    inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);
    

    该函数在成功时返回 1。

    Linux 上不需要调用WSAStartup以及与之相关的所有内容。

    该函数closesocket必须替换为close。该参数是一个套接字描述符sock。

    创建套接字的调用socket不会改变,它们在两个系统上是相同的。如果成功,该函数将返回一个非负类型描述符int。

    调用ioctlsocket需要更改为以下内容:

    int flags = fcntl(sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags | O_NONBLOCK);
    

    fcntl失败时返回 -1。作为替代方案,还有FIONBIO一个选项,但O_NONBLOCK它包含在 POSIX 标准中,FIONBIO我不建议使用它:

    int opt = 1;
    ioctl(sock, FIONBIO, &opt);
    

    两个系统上的调用sendto是相同的,就像recvfrom. 两个函数都在失败时返回 -1。

    因此,在所有调用中,有必要重新检查函数返回的值。同样在 Linux 上,套接字描述符的类型为int.

    笔记

    如果我是你,我会重新考虑你的代码结构的组织。您的两个类在许多方面相互重复,并且在某些地方存在未使用的变量。

    此外,正如test123 所指出的,您正在以非阻塞模式使用套接字,因此在套接字不存在时尝试从套接字获取数据将导致函数错误recvfrom。如果确实需要非阻塞套接字模式,可以使用select或pselect等待输入。

    如果你使用Qt,那么它也有自己的通过类处理套接字的版本QUdpSocket。它的描述在官方文档中。

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5