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;
}
相关推荐
所以遗憾是什么呢?9 小时前
【题解】Educational Codeforces Round 195 (Rated for Div. 2) ABCDE
c++·动态规划·acm·icpc·ccpc·xcpc·codeforecs
学逆向的9 小时前
C 循环结构的执行效率分析
c语言·开发语言·数据结构·网络安全
不昀10 小时前
网口Link Up后仍然掉线,怎样区分物理链路和数据通路问题?
linux·以太网
Lhan.zzZ10 小时前
Qt WebEngineView 在 Linux 上无法加载网页:从“看不见 HTML“到“禁用沙箱“
linux·c++·qt
Fcy64812 小时前
Linux下 多路转接select详解
linux·select·多路转接
sysu_chenxy12 小时前
二重循环输出二维图形
c++
无足鸟ICT12 小时前
【RHCA+】RPM包命名规则
linux·运维·服务器
Navigator_Z12 小时前
LeetCode //C - 1293. Shortest Path in a Grid with Obstacles Elimination
c语言·算法·leetcode
Zucker n13 小时前
一款适合研究生科研工作安排的日历
linux·数据库·python
爱吃香菜的初学者13 小时前
十六.Linux——多线程(2)
linux·运维·开发语言