Linux socket: udp server and client demo

一、server 端

1)创建socket,指定协议版本(v4,v6)、协议类型(udp、tcp),获得server fd。

2)bind本地地址

(1)通过server fd进行操作

(2)创建并设置sockaddr_in对象,设置对端的地址和端口信息:

server端,不指定具体的client地址,设置为INADDR_ANY

(3)指定监听端口

3)在server fd上启动监听。

4)接收client连接请求

(1)使用循环持续监听client请求

(2)收到client请求后,在server fd上调用accept获得client fd,client sockaddr_in对象

5)使用client fd进行收发数据

二、client 端

1)创建socket,指定协议版本和协议类型,获得server fd。

2)connect()连接服务器

(1)通过上面创建的server fd进行操作

(2)创建并设置sockaddr_in对象,设置对端的地址和端口信息:

client端,需要指定server的ip:port

(3)bind和connect入参相同,server fd, addr, addr_length

accept()函数参数类似,后两个参数为出参

3)完成连接后,通过server fd和服务器收发数据

cpp 复制代码
#include <iostream>
#include <thread>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <cassert>

using namespace std;

#define max_line 80
#define port 21339

void server_func() {
    cout << "server begin\n";
    struct sockaddr_in addr;

    // 1. create udp socket and get the server fd
    int server_fd = socket(PF_INET, SOCK_STREAM, 0);
    assert(server_fd != -1);

    bzero(&addr, sizeof(addr));
    addr.sin_family = PF_INET; // v4
    addr.sin_addr.s_addr = htonl(INADDR_ANY); // listen on any local address
    addr.sin_port = htons(port);

    // 2. bind local address with server fd
    bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));

    // 3. start listening on server fd
    int ret = listen(server_fd, 10);
    assert(ret != -1);
    cout << "server: start listening\n";

    struct sockaddr_in client_addr;
    socklen_t len = 0;
    char buf[max_line];
    char addr_str[INET_ADDRSTRLEN];

    // 4. loop and accept client's requests
    int count = 1;
    while(true) {
        cout << "server: begin loop: " << count++ << endl;
        bzero(&client_addr, sizeof(client_addr));
        // 4.1 accept a client's request and get the client fd for interaction
        // listen on server fd and get a client fd through the server fd
        int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);
        assert(client_fd != -1);

        inet_ntop(PF_INET, &client_addr.sin_addr, addr_str, sizeof(addr_str));
        printf("server: accept client -> [%s:%d]\n", addr_str, client_addr.sin_port);

        // 4.2 use the client fd to receive and send data
//        int n = read(client_fd, buf, max_line);
        int n = recv(client_fd, buf, max_line, 0);
        for (int i=0; i<n; i++) {
            buf[i] = toupper(buf[i]);
        }

        write(client_fd, buf, n);

        close(client_fd);
        cout << "server: end a loop.\n";
    }
}

void client_func() {
    cout << "client begin\n";

    const char* msg = "hello";
    char buf[max_line] = {0};

    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));

//    inet_pton(PF_INET, "127.0.0.1", &server_addr.sin_addr);
    server_addr.sin_family = PF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(port);

    // 1. create a socket
    int server_fd = socket(PF_INET, SOCK_STREAM, 0);
    assert(server_fd != -1);

    // 2. connect the socket and get the server fd
    int ret = connect(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    cout << "client: failed to connect server, since: " << strerror(errno) << endl;
    assert(ret != -1);

    int len = strlen(msg);
    // 3. send and receive data through the server fd
//    write(server_fd, msg, len);
    send(server_fd, msg, len, 0);

    read(server_fd, buf, len);
    cout << "read: " << buf << endl;

    cout << "client end\n";
    return;
}

int main() {
    jthread server(server_func);
    jthread client(client_func);

    std::cout << "Hello, World!" << std::endl;
    return 0;
}
相关推荐
码匠许师傅6 小时前
【设计模式精讲】29.行为型模式总结与对比(Behavioral Patterns Summary)
c++·设计模式·uml
隐擎fox6 小时前
深入理解网络传输层安全:TLS 指纹识别(JA3/JA4)原理与 Python 协议层检测实战
爬虫·python·网络协议·安全·网络安全·https
游戏开发爱好者86 小时前
网络连接排查指南,谁在电脑后台偷跑流量,哪些程序在联网
网络协议·计算机网络·网络安全·ios·adb·https·udp
Jeremy_WW6 小时前
QSFP/QSFP-DD/OSFP 通用管理接口规范(CMIS)解读:13 Page 9Fh
网络·网络协议·信息与通信·光模块·cmis
啦啦啦啦啦zzzz6 小时前
Logger的组装(c++20)
c++·算法·c++20
bosins7 小时前
WSL 迁移指南:如何将 Linux 环境完整复制到另一台电脑
linux·运维·服务器
繁星蓝雨8 小时前
C++的设计与演进大纲(如何从C语言一步步成长为C++)
c语言·开发语言·c++·c++历史·c++演进
yutian06068 小时前
C: Unix UTC 时间戳转为 UTC+8 北京时间
c语言·unix
蒸蒸yyyyzwd8 小时前
机试学习笔记
c++·求职招聘
企鹅的蚂蚁9 小时前
LubanCat RK3588 实时 Linux 开发(六):启用 gs_usb 驱动并完成 USB-CAN 收发
linux·rk3588·linux驱动·socketcan·gs_usb·usb-can