Linux c编程之UDP通信

这篇具有很好参考价值的文章主要介绍了Linux c编程之UDP通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、说明

  UDP(User Datagram Protocol),由RFC 768规范定义,中文名为用户数据报协议。UDP 为应用程序提供了一种无需建立连接就可以发送网络数据包的方法。
  UDP是常用的网络传输协议之一,该协议是无连接、不可靠、面向数据报的协议。在Linux C网络程序中广泛使用,如音、视频媒体数据传输、DNS协议、SIP协议等。
  UDP通信分为客户端和服务端,其中服务端在指定的网络端口上读取数据,客户端将数据发给服务端绑定的网络端口,无需建立连接即可通信,反过来,服务端向客户端发送数据也是一样。

二、常用API介绍

2.1 socket()

   #include <sys/types.h>
   #include <sys/socket.h>
   int socket(int domain, int type, int protocol);

作用:创建一个通信的终端
参数说明:
  domain: 协议族,常用AF_INET表示IPv4
  type: 传输方式,常用的有以下两种:
    SOCK_STREAM: TCP
    SOCK_DGRAM: UDP
  protol: 特殊协议,实际应用中都是写为0
返回值:
  成功时返回一个socket文件描述符,失败时返回-1,errno会被设置,可以通过errno值获取错误码

2.2 bind()

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,
            socklen_t addrlen);

作用:
  绑定网络地址(IP/PORT)到socket
参数说明:
  sockfd: socket()返回的描述符
  addr: 绑定的地址
  addrlen: 绑定的地址结构长度
返回值:
  成功时返回0,失败时返回-1,errno会被设置,可以通过errno值获取错误码

2.3 sendto()

#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len,
             int flags, const struct sockaddr *dest_addr,
              socklen_t addrlen);

作用:
  发送消息
参数说明:
  sockfd: socket()创建的socket描述符
  buf: 发送的内容(起始地址)
  len:发送内容的长度
  flags: 发送选项,一般为0
  dest_addr:目的地址
  addrlen:目的地址长度
返回值:
  成功返回发送的字符个数,失败返回-1,errno会被设置

2.4 recvfrom()

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len,
                 int flags, struct sockaddr *src_addr,
                 socklen_t *addrlen);

作用:
  接收消息
参数说明:
  sockfd: socket()创建的socket描述符
  buf: 接收的内容(起始地址)
  len:接收内容的长度
  flags: 接收选项,一般为0
  dest_addr:源地址
  addrlen:源地址长度
返回值:
  成功时返回接收的字节数,错误时返回-1,并设置errno值。如果对端关闭时,返回0

2.5 close()

#include <unistd.h>
int close(int fd);

作用:
  关闭一个(文件/socket)描述符
参数说明:
  fd: 描述符

三、UDP实例分析

3.1 基本UDP通信示例

server_udp.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 9999

int server_udp()
{
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    char buf[1024] = {0};
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    addr_len = sizeof(server_addr);
    ret = bind(socket_fd, (const struct sockaddr *)&server_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

    while (1) {
        memset(buf, 0, sizeof(buf));
        addr_len = sizeof(client_addr);
        ret = recvfrom(socket_fd, buf, sizeof(buf), 0,
                         (struct sockaddr *)&client_addr, &addr_len);
        if (ret > 0) {
            printf("recv len:%d, data:[%s] from %s:%d\n", ret, buf,
                    inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        } else if (0 == ret) {
            printf("ret:%d\n", ret);
        } else {
            printf("ret:%d\n", ret);
        }
    }

    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    server_udp();

    return 0;
}

client_udp.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 9999

int client_udp(char *data)
{
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    addr_len = sizeof(server_addr);
    ret = sendto(socket_fd, data, strlen(data), 0,
                     (struct sockaddr *)&server_addr, addr_len);
    if (ret > 0) {
        printf("send data: [%s] to %s:%d\n", data, inet_ntoa(server_addr.sin_addr),
                        ntohs(server_addr.sin_port));
    } else {
        printf("ret:%d\n", ret);
    }

    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        client_udp("hello world");
    } else {
        client_udp(argv[1]);
    }

    return 0;
}

Makefile:

all:
	gcc -o server server_udp.c
	gcc -o client client_udp.c
clean:
	-@rm server client

编译方式:

make

测试运行:

$ ./client
send data: [hello world] to 127.0.0.1:9999
$ ./server
recv len:11, data:[hello world] from 127.0.0.1:44180

$ ./client "I can do it"
send data: [I can do it] to 127.0.0.1:9999
$ ./server
recv len:11, data:[I can do it] from 127.0.0.1:43607

3.2 客户端端口变化问题

  在3.1的例子中,客户端重复调用时,服务端收到的数据是从客户端不同的端口发来的,如下:

$ ./server
recv len:1, data:[1] from 127.0.0.1:43113
recv len:1, data:[2] from 127.0.0.1:46748
recv len:1, data:[3] from 127.0.0.1:43452

  客户端端口变化是由于客户端的socket没有绑定固定的端口,系统每次随机分配了一个端口。可以使用bind函数绑定固定端口,如下代码所示:

memset(&client_addr, 0, sizeof(client_addr));                                                                                        
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(CLIENT_PORT);
    client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP);
    addr_len = sizeof(client_addr);

    ret = bind(socket_fd, (const struct sockaddr *)&client_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

客户端绑定端口后,再次测试验证:可以看到客户端的端口一直是绑定的端口10000

$ ./server
recv len:1, data:[1] from 127.0.0.1:10000
recv len:1, data:[2] from 127.0.0.1:10000
recv len:1, data:[3] from 127.0.0.1:10000

3.3 服务器向客户端回写消息

server.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 9999

int server_udp()
{
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    char buf[1024] = {0};
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    addr_len = sizeof(server_addr);
    ret = bind(socket_fd, (const struct sockaddr *)&server_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

    while (1) {
        memset(buf, 0, sizeof(buf));
        addr_len = sizeof(client_addr);
        ret = recvfrom(socket_fd, buf, sizeof(buf), 0,
                         (struct sockaddr *)&client_addr, &addr_len);
        if (ret > 0) {
            printf("recv len:%d, data:[%s] from %s:%d\n", ret, buf,
                    inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
            addr_len = sizeof(client_addr);
            ret = sendto(socket_fd, buf, ret, 0,
                    (struct sockaddr *)&client_addr, addr_len);
            if (ret > 0) {
                printf("send data: [%s] to %s:%d\n", buf, inet_ntoa(client_addr.sin_addr),
                        ntohs(client_addr.sin_port));
            } else {
                printf("ret:%d\n", ret);
            }

        } else if (0 == ret) {
            printf("ret:%d\n", ret);
        } else {
            printf("ret:%d\n", ret);
        }
    }

    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    server_udp();

    return 0;
}

client.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 9999
#define CLIENT_IP "127.0.0.1"
#define CLIENT_PORT 10000

int client_udp(char *data)
{
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    char buf[1024] = {0};
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    memset(&client_addr, 0, sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(CLIENT_PORT);
    client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP);
    addr_len = sizeof(client_addr);

    ret = bind(socket_fd, (const struct sockaddr *)&client_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

    addr_len = sizeof(server_addr);
    ret = sendto(socket_fd, data, strlen(data), 0,
                     (struct sockaddr *)&server_addr, addr_len);
    if (ret > 0) {
        printf("send data: [%s] to %s:%d\n", data, inet_ntoa(server_addr.sin_addr),
                        ntohs(server_addr.sin_port));
    } else {
        printf("ret:%d\n", ret);
    }

    memset(buf, 0, sizeof(buf));
    addr_len = sizeof(server_addr);
    ret = recvfrom(socket_fd, buf, sizeof(buf), 0,
            (struct sockaddr *)&server_addr, &addr_len);
    if (ret > 0) {
        printf("recv len:%d, data:[%s] from %s:%d\n", ret, buf,
                inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port));
    } else if (0 == ret) {
        printf("ret:%d\n", ret);
    } else {
        printf("ret:%d\n", ret);
    }


    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        client_udp("hello world");
    } else {
        client_udp(argv[1]);
    }

    return 0;
}

测试:

$ ./client "hello world"
send data: [hello world] to 127.0.0.1:9999
recv len:11, data:[hello world] from 127.0.0.1:9999

$ ./server
recv len:11, data:[hello world] from 127.0.0.1:10000
send data: [hello world] to 127.0.0.1:10000

3.4 服务端状态和行为

服务器不启动时,客户端发送消息时,会出现icmp的端口不可达报文,如下:
linux c udp,Linux C网络编程实践,udp,linux,c语言,sendto,recvfrom
服务端启动时,可以通过netstat命令查看服务端接收消息的网络端口

$ ./server

$ netstat -anp | grep 9999
udp        0      0 0.0.0.0:9999            0.0.0.0:*                           21845/server 

3.5 非阻塞模式

  socket默认是阻塞模式,因此调用recvfrom()函数时,如果没有客户端发送数据,则recvfrom会一直阻塞,导致程序挂住,不能处理其它事情。因此,在实际应用场景中,会将socket设置为非阻塞。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>

#define SERVER_PORT 9999

int server_udp()
{
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    char buf[1024] = {0};
    int flag = 0;
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    flag = fcntl(socket_fd, F_GETFL, 0);
    flag = flag | O_NONBLOCK;
    fcntl(socket_fd, F_SETFL, flag);

    addr_len = sizeof(server_addr);
    ret = bind(socket_fd, (const struct sockaddr *)&server_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

    while (1) {
        memset(buf, 0, sizeof(buf));
        addr_len = sizeof(client_addr);
        ret = recvfrom(socket_fd, buf, sizeof(buf), 0,
                         (struct sockaddr *)&client_addr, &addr_len);
        if (ret > 0) {
            printf("recv len:%d, data:[%s] from %s:%d\n", ret, buf,
                    inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        } else if (0 == ret) {
            printf("ret:%d\n", ret);
        } else {
            if (EAGAIN == errno) {
                printf("ret:%d, errno:%d, %s\n", ret, errno, strerror(errno));
            } else {
                printf("ret:%d, errno:%d, %s\n", ret, errno, strerror(errno));
            }
        }
    }

    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    server_udp();

    return 0;
}

测试:

$ ./server
ret:-1, errno:11, Resource temporarily unavailable                                                                                       
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
ret:-1, errno:11, Resource temporarily unavailable
................................................................

通过轮询的方式调用recvfrom接口时,会出现循环打印日志的情况。
为了解决这个问题,使用IO复用函数epoll来处理socket,只在有数据的时候才调用,示例如下:
server.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/epoll.h>

#define SERVER_PORT 9999

int server_udp()
{
    int i = 0;
    int num = 0;
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    char buf[1024] = {0};
    int flag = 0;
    int epoll_fd = -1;
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;
    struct epoll_event event;
    struct epoll_event events_array[10];

    epoll_fd = epoll_create(10);
    if (epoll_fd < 0) {
        printf("epoll_create failure:%s\n", strerror(errno));
        return -1;
    }

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    flag = fcntl(socket_fd, F_GETFL, 0);
    flag = flag | O_NONBLOCK;
    fcntl(socket_fd, F_SETFL, flag);

    addr_len = sizeof(server_addr);
    ret = bind(socket_fd, (const struct sockaddr *)&server_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

    event.events =  EPOLLIN;
    event.data.fd = socket_fd;
    ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event);
    if(ret < 0) {
        printf("epoll_trl failure:%s\n", strerror(errno));
        close(epoll_fd);
        return -1;
    }

    while (1) {
        num = epoll_wait(epoll_fd, events_array, 10, 10000);
        if(num < 0) {
            printf("epoll_wait failure:%s\n", strerror(errno));
            close(epoll_fd);
            break;
        } else if(num == 0) {
            printf("eopll_wait timeout!\n");
            continue;
        }

        for (i = 0; i < num; i++) {
            if(events_array[i].events == EPOLLIN) {
                ret = recvfrom(socket_fd, buf, sizeof(buf), 0,
                        (struct sockaddr *)&client_addr, &addr_len);
                if (ret > 0) {
                    printf("recv len:%d, data:[%s] from %s:%d\n", ret, buf,
                            inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                } else if (0 == ret) {
                    printf("ret:%d\n", ret);
                } else {
                    if (EAGAIN == errno) {
                        printf("ret:%d, errno:%d, %s\n", ret, errno, strerror(errno));
                    } else {
                        printf("ret:%d, errno:%d, %s\n", ret, errno, strerror(errno));
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events_array[i].data.fd, NULL);
                    }
                }
            }
        }
    }

    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    server_udp();

    return 0;
}

client.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 9999
#define CLIENT_IP "127.0.0.1"
#define CLIENT_PORT 10000

int client_udp(char *data)
{
    int ret = 0;
    int socket_fd = -1;
    int addr_len = 0;
    char buf[1024] = {0};
    struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;

    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd < 0) {
        printf("%s: socket failed\n", __FUNCTION__);
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    memset(&client_addr, 0, sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(CLIENT_PORT);
    client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP);
    addr_len = sizeof(client_addr);

    ret = bind(socket_fd, (const struct sockaddr *)&client_addr, addr_len);
    if (ret < 0) {
        printf("%s: bind failed\n", __FUNCTION__);
        close(socket_fd);
        return 0;
    }

    addr_len = sizeof(server_addr);
    ret = sendto(socket_fd, data, strlen(data), 0,
                     (struct sockaddr *)&server_addr, addr_len);
    if (ret > 0) {
        printf("send data: [%s] to %s:%d\n", data, inet_ntoa(server_addr.sin_addr),
                        ntohs(server_addr.sin_port));
    } else {
        printf("ret:%d\n", ret);
    }

    close(socket_fd);

    return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        client_udp("hello world");
    } else {
        client_udp(argv[1]);
    }

    return 0;
}

测试 :文章来源地址https://www.toymoban.com/news/detail-732900.html

$ ./client 1
send data: [1] to 127.0.0.1:9999
$ ./client 2
send data: [2] to 127.0.0.1:9999
$ ./client 3
send data: [3] to 127.0.0.1:9999
$ ./client 
send data: [hello world] to 127.0.0.1:9999

$ ./server
recv len:1, data:[1] from 127.0.0.1:10000
recv len:1, data:[2] from 127.0.0.1:10000
recv len:1, data:[3] from 127.0.0.1:10000
recv len:11, data:[hello world] from 127.0.0.1:10000
eopll_wait timeout!

四、关键说明

  • UDP 是无连接的,即发送数据之前不需要像TCP那样建立连接,因此减少了建立连接带来的开销和发送数据的时延
  • UDP 数据是面向报文传输的。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界,因此不涉及到粘包问题。不过应用程序必须选择合适大小的报文。
  • UDP 没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。
  • UDP适用于实时性要求很高,并且几乎不能容忍重传的应用场景,比如直播
  • UDP适用于应用程序对传输的可靠性要求不高,但是对传输速度和延迟要求较高的场景。UDP适合于实时数据传输,如VoIP中的语音和视频通信,因为这种场景在偶尔丢失一两个或少量数据包时,对接收方也不会造成太大的影响

到了这里,关于Linux c编程之UDP通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】网络基础+UDP网络套接字编程

    只做自己喜欢做的事情,不被社会和时代裹挟着前进,是一件很奢侈的事。 1. 首先计算机是人类设计出来提高生产力的工具,而人类的文明绵延至今一定离不开人类之间互相的协作,既然人类需要协作以完成更为复杂的工作和难题,所以计算机作为人类的工具自然也一定需要

    2024年02月08日
    浏览(59)
  • 【Linux网络】网络编程套接字(预备知识+UDP)

    目录 预备知识 1. 理解源IP地址和目的IP地址 2. 理解源MAC地址和目的MAC地址 3. 认识端口号  4. 理解源端口号和目的端口号 5. 端口号(port) vs 进程pid 6. 认识TCP协议和认识UDP协议 7. 网络字节序 socket编程接口  1. socket 常见API 2. sockaddr结构  简单的UDP网络程序  1. 服务端创建udp

    2024年02月19日
    浏览(55)
  • 【Linux网络编程】基于UDP实现多人聊天室

    UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。 数据报格式套接字 SOCK_DGRAM 采用UDP只管发送数据而不去验证发送数据的正确性,不论传输是否被接收,数据流是否有丢失,都不再重新发

    2024年02月08日
    浏览(52)
  • 【Linux Network】网络编程套接字(代码练习)—UDP

    目录 1. 常用接口 2. C/S 回声模拟 3. C/S myshell 的制作  Linux网络编程✨ 1. 常用接口 socket:创建套接字: 返回值: 套接字创建成功返回一个文件描述符 ,创建失败返回-1,同时错误码会被设置。 参数: domain: 网络通信 设置为 AF_INET(IPv4)或AF_INET6(IPv6) ; type:基于 UDP的网

    2024年02月03日
    浏览(89)
  • 【Linux网络】网络编程套接字 -- 基于socket实现一个简单UDP网络程序

    我们把数据从A主机发送到B主机,是目的吗?不是,真正通信的不是这两个机器!其实是这两台机器上面的软件(人) 数据有 IP(公网) 标识一台唯一的主机 ,用谁来标识各自主机上客户或者服务进程的唯一性呢? 为了更好的表示一台主机上服务进程的唯一性,我们采用 端口号

    2024年02月12日
    浏览(131)
  • 初学记录【linux应用】 TCP/UDP 网络编程 C语言

    以下内容分别为TCP 与 UDP编程,内容有相似或者重合部分,可根据流程 相互对照学习,都已经附上源码 。 **1.** socket 创建 tcp套接字 (监听的套接字) 2、IPv4套接字地址结构 #include netinet/in.h struct in_addr: 如果使用 Internet 所以 sin_family 一般为 AF_INET。 ⚫ sin_addr 设置为 INADDR_AN

    2024年02月03日
    浏览(62)
  • C/C++ Linux Socket网络编程 TCP 与 UDP

    之前已经学习了QT的socket编程 和 C/C++在window环境的socket编程,现在再来学习一波C/C++在Linux环境下的socket编程,为以后学习C++ Linux 服务器开发做准备。 目录 一、Socket简介 二、Socket编程基础 1. 网络字节序 2. sockaddr数据结构 3. IP地址转换函数 三、TCP编程函数 1. socket函数 2. bi

    2024年02月02日
    浏览(58)
  • 【探索Linux】P.28(网络编程套接字 —— 简单的UDP网络程序模拟实现)

    在前一篇文章中,我们详细介绍了UDP协议和TCP协议的特点以及它们之间的异同点。 本文将延续上文内容,重点讨论简单的UDP网络程序模拟实现 。通过本文的学习,读者将能够深入了解UDP协议的实际应用,并掌握如何编写简单的UDP网络程序。让我们一起深入探讨UDP网络程序的

    2024年04月08日
    浏览(154)
  • 【QT网络编程】实现UDP协议通信

    Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了 一种无需建立连接就可以发送封装的 IP 数据包的方法 。RFC 768 描述了 UDP。 UDP协议根据消息传送模式可以分为: 单播(Unicast)、组播(Multicast)和广播(

    2024年02月02日
    浏览(52)
  • 基于UDP/TCP的网络通信编程实现

    红色是心中永不褪色的赤诚 操作系统为网络编程提供了 Socket api , Socket是基于TCP/IP协议的网络通信的基本单元, 基于Socket的网络程序开发就是 网络编程. 由于直接与应用层联系的是传输层, 所以针对应用层协议(TCP, UDP), Shocket提供了三种套接字, 分别是 流套接字(使用TCP) , 数据报

    2024年02月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包