linux系统编程(十②)RK3568 socket之 TCP 客户端的实现

开发环境

1、讯为RK3568开发板,下载了Ubuntu系统。

2、笔记本Windows下的VScode连接开发板。

3、网线连接开发板J13网口。

VSCode远程连接开发板:https://blog.csdn.net/u012507643/article/details/152666866?spm=1011.2124.3001.6209

UDP收发的流程:

创建socket->bind->connect->sendto/recvfrom/send/recv

一、用到的函数

函数参考前面写的一片博客,这里不复制过来了

https://blog.csdn.net/u012507643/article/details/153478108?sharetype=blogdetail&sharerId=153478108&sharerefer=PC&sharesource=u012507643&spm=1011.2480.3001.8118

二、直接看实际代码

复制代码
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <errno.h>


int main(int argc, char *argv[])
{
    int fd;
    int conn = 0;
    int ret = 0;
    char tx_buf[1024] = {"12324"}, rx_buf[1024] = {0};
    struct sockaddr_in cs;

    //SOCK_STREAM:TCP
    fd = socket(AF_INET, SOCK_STREAM, 0);

    inet_pton(AF_INET, "192.168.31.20", &cs.sin_addr);
    cs.sin_family = AF_INET;
    cs.sin_port = htons(8080);
    bind(fd, (const struct sockaddr *)&cs, sizeof(cs));

    while(1)
    {

        if (conn == 0)
        {
            if (connect(fd, (const struct sockaddr *)&cs, sizeof(cs)) < 0)
            {
                //printf("connect failed\n");
            }
            else
            {
                printf("connectted server\n");
                conn = 1;
            }
        }
        else
        {
            // struct tcp_info info;
            int len = sizeof(cs);

            /* 这里才是真正的数据 */
            ret = recv(fd, rx_buf, sizeof(rx_buf) - 1, MSG_DONTWAIT);
            if (ret > 0)
            {
                    printf("recv data:%s, len=%d\n", rx_buf, ret);
                    // printf("input data:\n");
                    // scanf("%s", tx_buf);
                    if (sendto (fd, rx_buf, ret, MSG_DONTWAIT, (struct sockaddr *)&cs, sizeof(cs)) < 0)
                    {
                        
                        printf("server abroad\n");
                        conn = 0;
                    }
                    memset(tx_buf, 0, sizeof(tx_buf));
                    memset(rx_buf, 0 ,sizeof(rx_buf));
            }

            /* 这里仅仅作为探针,看下连接是否断开 */
            ret = recv(fd, rx_buf, sizeof(rx_buf) - 1, MSG_PEEK);
            if ((ret > 0) || ((ret == -1) && (errno == EAGAIN)))
            {
                continue;
            }
            else
            {
                printf("server abroad\n");
                conn = 0;
                close(fd);
                fd = socket(AF_INET, SOCK_STREAM, 0);
            }
        }
    }
    close(fd);

    return 0;
}

三、测试结果

1、测试连接

2、测试断开重连【网络助手断开重新侦听】

3、测试收发数据

四、总结

1、这里增加判断远程是否断开:

使用recv() 函数的MSG_PEEK选项,使用这个选项可以"偷看(peek)"一下接收队列的数据。所谓"偷看",就是recv()不从接收队列中把数据移除,因此下一次调用recv()函数还会接收到此数据。

当TCP连接处于已建立Established状态时,如果接收队列中有数据,recv()函数返回实际接收的字节数;如果接收队列中没有数据但是TCP连接没有断开,recv() 函数返回-1,并且把errno设置为EAGAIN。其余情况下表示TCP连接已经断开。

所以上面我使用了两次的recv函数,一个是接收数据用,一个是判断是否断开了。

2、重连时候需要close掉上一次的套接字描述符,否则直接connect是失败的。

由于本人也是刚学,写的不好,也不规范,有错误的地方望前辈指正,以免误入歧途。

相关推荐
confiself1 小时前
GO环境配置
linux·运维·centos
爱装代码的小瓶子1 小时前
【c++与Linux基础】文件篇(4)虚拟文件系统VFS
linux·开发语言·c++
JiMoKuangXiangQu7 小时前
ARM64 进程虚拟地址空间布局
linux·arm64 虚拟地址布局
阳光九叶草LXGZXJ7 小时前
达梦数据库-学习-47-DmDrs控制台命令(LSN、启停、装载)
linux·运维·数据库·sql·学习
春日见7 小时前
如何避免代码冲突,拉取分支
linux·人工智能·算法·机器学习·自动驾驶
无垠的广袤8 小时前
【VisionFive 2 Lite 单板计算机】边缘AI视觉应用部署:缺陷检测
linux·人工智能·python·opencv·开发板
阿波罗尼亚8 小时前
Kubectl 命令记录
linux·运维·服务器
一轮弯弯的明月8 小时前
TCP传输大致过程、流量控制与拥塞控制
网络·tcp/ip·计算机网络·学习心得
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.8 小时前
Keepalived单播模式配置与实战指南
linux·服务器·负载均衡
IDC02_FEIYA9 小时前
Linux文件搜索命令有哪些?Linux常用命令之文件搜索命令find详解
linux·运维·服务器