udp_client函数

#include    <netdb.h>
#include    <stdlib.h>
#include    <string.h>
#include    <sys/socket.h>

#define     SA     struct sockaddr

int
udp_client(const char *host, const char *serv, SA **saptr, socklen_t *lenp)
{
    int                sockfd, n;
    struct addrinfo    hints, *res, *ressave;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
        err_quit (
            "udp_client error for %s, %s: %s",
            host, serv, gai_strerror(n)
        );
    }
    ressave = res;

    do {
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if (sockfd >= 0) {
            break;        /* success */
        }
    } while ( (res = res->ai_next) != NULL);

    if (res == NULL) {    /* errno set from final socket() */
        err_sys("udp_client error for %s, %s", host, serv);
    }

    *saptr = malloc(res->ai_addrlen);
    memcpy(*saptr, res->ai_addr, res->ai_addrlen);
    *lenp = res->ai_addrlen;

    freeaddrinfo(ressave);

    return(sockfd);
}

 

转载于:https://www.cnblogs.com/soldierback/p/10744873.html

### UDP Socket 函数使用方法与示例 #### 基础概念 UDP 是一种面向无连接的协议,适用于数据传输不需要可靠性的场景。通过 `socket`、`sendto`、`bind` 和 `recvfrom` 等函数可以实现基于 UDP网络通信。 --- #### 1. 创建套接字 (Socket) 创建一个 UDP 套接字需要调用 `socket()` 函数。该函数的功能是初始化一个新的套接字并返回对应的文件描述符[^1]。 ```c int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockfd < 0) { perror("Failed to create socket"); } ``` - **参数解释**: - `AF_INET`: 表示 IPv4 地址族。 - `SOCK_DGRAM`: 指定使用 UDP 协议(数据报方式)。 - `IPPROTO_UDP`: 明确指定协议为 UDP。 --- #### 2. 绑定地址和端口 (Bind) 为了使服务器能够监听特定的 IP 地址和端口号,需调用 `bind()` 将这些信息绑定到已创建的套接字上[^3]。 ```c struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; // 设置地址族为 IPv4 server_addr.sin_port = htons(8080); // 设置端口号为 8080 server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有本地网卡上的请求 if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Binding failed"); } ``` - 如果绑定失败,通常是因为端口被占用或其他配置错误。此时可以通过检查全局变量 `errno` 获取具体原因。 --- #### 3. 发送数据 (Sendto) 客户端发送消息给目标主机时,可利用 `sendto()` 实现。此函数允许直接向某个远程地址发送数据包而无需事先建立连接。 ```c char message[] = "Hello from client!"; struct sockaddr_in dest_addr; dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(9090); // 对方端口设为 9090 inet_pton(AF_INET, "127.0.0.1", &dest_addr.sin_addr); ssize_t bytes_sent = sendto(sockfd, message, strlen(message), 0, (const struct sockaddr*)&dest_addr, sizeof(dest_addr)); if (bytes_sent < 0) { perror("Sending data failed"); } else { printf("%zd bytes sent\n", bytes_sent); } ``` --- #### 4. 接收数据 (Recvfrom) 当服务器准备好接收来自任意客户的输入时,它会阻塞直到有新的数据到达为止。这时可以用 `recvfrom()` 来获取传入的数据及其源地址信息。 ```c #define BUFFER_SIZE 1024 char buffer[BUFFER_SIZE]; struct sockaddr_in src_addr; socklen_t addr_len = sizeof(src_addr); ssize_t bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr*)&src_addr, &addr_len); if (bytes_received > 0) { buffer[bytes_received] = '\0'; printf("Received %zd bytes: '%s'\n", bytes_received, buffer); } else { perror("Receiving data failed"); } ``` 注意,在多线程环境中,虽然同一 `sockfd` 可以安全地用于并发读写操作[^2],但仍应小心处理可能的竞争条件或资源争抢情况。 --- ### 完整代码示例 以下是完整的 C 语言程序展示如何构建简单的 UDP Echo Server/Client: #### UDP Client Example ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> int main(void){ int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); char msg[]="Test Message"; struct sockaddr_in servaddr; memset((char *) &servaddr, 0, sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK); servaddr.sin_port=htons(5000); sendto(sockfd,msg,strlen(msg)+1,MSG_CONFIRM,(struct sockaddr *)&servaddr,sizeof(servaddr)); close(sockfd); return 0; } ``` #### UDP Server Example ```c #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> void die(char *msg){perror(msg); exit(1);} int main(){ int sock_fd; if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))<0 ) die("socket"); struct sockaddr_in localAddr={0}; localAddr.sin_family = AF_INET; localAddr.sin_port = htons(5000); localAddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock_fd , (struct sockaddr*)&localAddr ,sizeof(localAddr))==-1)die("bind"); while(1){ char buf[BUFSIZ]={0}; struct sockaddr_in cliAddr={0}; socklen_t clilen=sizeof(cliAddr); ssize_t n=read(sock_fd,buf,BUFSIZ-1); if(n<=0)continue; write(STDOUT_FILENO,"Message Received:",strlen("Message Received:")); write(STDOUT_FILENO,buf,n); } } close(sock_fd ); return 0 ; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值