分类 Ubuntu 下的文章

“Ubuntu是以桌面应用为主的Linux发行版,基于Debian。Ubuntu有三个正式版本,包括桌面版、服务器版及用于物联网设备和机器人的Core版。从17.10版本开始,Ubuntu以GNOME为默认桌面环境。 Ubuntu是著名的Linux发行版之一,也是目前最多用户的Linux版本。 ”

选择左边的 通用辅助,在右边开启 大号文本。
ubuntu-font-size.png

现在回到桌面,就会发现桌面图标文字变大,其它工具的字体也变大了。

以上就是ubuntu字体变大的技巧

protobuf 交叉编译 for arm

github 地址:https://github.com/protocolbuffers/protobuf

下载最新版3.17.3

wget https://github.com/protocolbuffers/protobuf/archive/refs/tags/v3.17.3.zip
mv v3.17.3.zip protobuf-v3.17.3.zip
unzip protobuf-v3.17.3.zip
cd protobuf-3.17.3/
./autogen.sh 
CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ ./configure --prefix=$(pwd)/install --host=arm-linux

会提示没有googletest,可以不用理他。

make && make install

受不了太慢

make -j8 && make install

cd install/lib
tree

.
├── libprotobuf.a
├── libprotobuf.la
├── libprotobuf-lite.a
├── libprotobuf-lite.la
├── libprotobuf-lite.so -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28 -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28.0.3
├── libprotobuf.so -> libprotobuf.so.28.0.3
├── libprotobuf.so.28 -> libprotobuf.so.28.0.3
├── libprotobuf.so.28.0.3
├── libprotoc.a
├── libprotoc.la
├── libprotoc.so -> libprotoc.so.28.0.3
├── libprotoc.so.28 -> libprotoc.so.28.0.3
├── libprotoc.so.28.0.3
└── pkgconfig

├── protobuf-lite.pc
└── protobuf.pc

1 directory, 17 files

file libprotobuf.so.28.0.3 

libprotobuf.so.28.0.3: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=3dc132b70a58e7012b755b18f076ff625359ef59, with debug_info, not stripped

编译好的头文件与lib文件下载包
protobuf-3.17.3-arm.tar.xz

经常使用UDP发送数据,但一般都是小包,没有太关注过发送大包的问题。突然要发个大包,c++ udp send big packet。
就tcpdump wireshark抓包看了一下。
结果在tcpdump中,出现了这个东西。
UDP, bad length 5455 > 1472
看来UDP包长度超过MTU了。应该是分片了,但分片就分片,只要网络可靠,应该都没什么问题。

另外就是怕UDP的接收或者发送缓冲区不够了。

udp setsockopt sendbuf example

还有多网卡的问题。直接指定网卡,这个要用到struct ifreq.这是linux下的用法。
windows好像没有这个SO_BINDTODEVICE选项,不过可以使用静态路由的方式。可以参考这个链接:
多网卡指定网卡进行UDP通信(添加静态路由解决双网卡问题 )全记录
最后代码如下:

注意 struct ifreq 头文件如下: struct ifreq header file

#include <sys/ioctl.h>
#include <net/if.h>

int cudp::udp_send(string ip, int port, string data)
{
    printf("udp_send ip=%s,port=%d\n",ip.c_str(),port);
    int m_nsockfd;
    if ((m_nsockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        printf("udp_send error.\n");
        return -1;
    }
    struct ifreq ifr;
    memset(&ifr, 0x00, sizeof(ifr));
    strncpy(ifr.ifr_name, "eth0", 4);
    setsockopt(m_nsockfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr));

    int addrlen = sizeof(sockaddr_in);
    struct sockaddr_in addr;
    bzero(&addr, sizeof(struct sockaddr_in));    
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    int sendbuff;
    socklen_t optlen;
    int res = 0;

    // Get buffer size
    optlen = sizeof(sendbuff);
    res = getsockopt(m_nsockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);

    if(res == -1)
        printf("Error getsockopt one");
    else
        printf("send buffer size = %d\n", sendbuff);

    sendbuff = 50*1024;

    printf("sets the send buffer to %d\n", sendbuff);
    res = setsockopt(m_nsockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));

    if(res == -1)
        printf("Error setsockopt");
        
    int ret = sendto(m_nsockfd, data.data(), data.length(), 0, (struct sockaddr *)&addr, addrlen);
    printf("sendto ret = %d\n", ret);
    return ret;
}

linux下可以直接拿来使用,用第一个示例就好了。

注意 struct ifreq 头文件如下: struct ifreq header file

#include <sys/ioctl.h>
#include <net/if.h>

这是代码的方法,肯定也有指定路由的办法。有兴趣的话可以了解一下。大致思路就是使用

route add ...
  1. example(TCP, UDP, RAW):

    int sock;
    struct ifreq ifr;
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    memset(&ifr, 0x00, sizeof(ifr));
    strncpy(ifr.ifr_name, "eth0", IFNAMSIZE);
    setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr));
    
  2. example(PACKET):

    int sock;
    struct sockaddr_ll sl;
    struct ifreq ifr;
    sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IPV6));
    memset(&sl, 0x00, sizeof(sl));
    memset(&ifr, 0x00, sizeof(ifr));
    sl.sll_family = AF_PACKET;
    sl.sll_protocol = htons(ETH_P_IPV6);
    strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
    ioctl(fd, SIOCGIFINDEX, &ifr);
    sl.sll_ifindex = ifr.ifr_ifindex;
    bind(fd, (struct sockaddr *)&sl, sizeof(sl));
    
  3. example(PACKET):

    int sock;
    struct sockaddr addr;
    sock = socket(PF_PACKET, SOCK_PACKET, ETH_P_IP);
    memset(&addr, 0x00, sizeof(addr));
    addr.sa_family = PF_PACKET;
    strncpy(addr.sa_data, "eth0", sizeof(addr.sa_data));
    bind(sock, &addr, sizeof(addr));
    

SO_BINDTODEVICE套接口选项说明:
SO_BINDTODEVICE
Bind  this  socket  to  a particular device like “eth0”, as specified in the passed interface name.  If the name is an empty string or the option length is zero, the socket device binding  is  removed.   The  passed option  is a variable-length null-terminated interface name string with the maximum size of IFNAMSIZ.  If a socket is bound to an interface, only packets received from that particular interface are processed by  the socket.  Note  that  this  only works for some socket types, particularly AF_INET sockets.  It is not supported for packet sockets (use normal bind(8) there).
Referenced from:https://blog.csdn.net/networkangle/article/details/52549758?tdsourcetag=s_pcqq_aiomsg

c++ udp send big packet

UDP datagram 大小限制 65,535 bytes

测试socket udp 单次传输数据上限(sendto()函数data不能超过65507字节。udp头占8字节,ip头占20字节,加起来正好65535字节)

void udp_test()
{
    char *p = new char[65507];
    string strsend;
    strsend.assign(p, 65507);
    int ret = udp_send("127.0.0.1", 8888, strsend);
    printf("udp_send ret=%d\n", ret);
    delete[] p;
}

udp_send ip=127.0.0.1,port=8888
send buffer size = 163840
sendto ret = 65507
udp_send ret=65507

void udp_test()
{
    char *p = new char[65508];
    string strsend;
    strsend.assign(p, 65508);
    int ret = udp_send("127.0.0.1", 8888, strsend);
    printf("udp_send ret=%d\n", ret);
    delete[] p;
}

udp_send ip=127.0.0.1,port=8888
send buffer size = 163840
sendto ret = -1
udp_send ret=-1

UDP仅提供数据报作为IP数据包的数据部分,IP数据包具有16位长度的字段,因此将数据限制为2 ^ 16字节(包括标题),或UDP数据部分的65507字节(假设没有ipv4选项) ,除了用UDP处理更大的数据包外,除了将它们分成几个数据包并自行处理重组等之外,没有其他方法。

UDP规范在UDP报头中为您提供16位的数据包大小,这意味着您一次发送的字节数不能超过65k。您必须将数据拆分为多个数据包。使用TCP代替UDP将使事情变得更加简单,因为可以确保完整性和接收顺序。