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;
}
相关推荐
布莱克6051 小时前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
honsor2 小时前
SNMP 读取以太网温湿度传感器数据,监控平台对接实操
物联网·网络协议·tcp/ip
揽星河..5 小时前
【C语言】底层程序设计
c语言·开发语言
lzx_0025 小时前
Linux 进程(二) 深入理解进程
linux
Yves..5 小时前
HTTP 协议学习笔记:从报文结构到抓包实践
网络协议·http·fiddler
沫璃染墨6 小时前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互
温暖小土6 小时前
在 CentOS 上安装 Redis Stack
linux·redis·centos
xiaoye-duck7 小时前
《C++ 项目:手写大模型接入 SDK》DeepSeek接口设计(下):流式响应实现和测试
开发语言·网络·c++·语言模型
GeW8 小时前
国产化替代进入深水区之后Linux 与数据库为什么必须走向重建
linux
旖旎夜光8 小时前
【C++ 基础入门】类和对象(上):封装、对象模型与 this 指针
开发语言·c++·笔记·学习