Linux UDP服务器编程

UDP主要使用sendto()recvfrom()
在这里插入图片描述

recvfrom()

函数原型如下:

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);


if (recvfrom(sockfd_s, buf, BUFFERSIZE, 0, (struct sockaddr*)&client_addr, &addrlen) == -1) {
            perror("recvfrom");
            continue;       //UDP无连接传输,偶尔传输失败一次继续执行
        }

特别注意:

  • sockfd是本地套接字的描述符,在服务器端,就是服务器套接字;在客户端,就是客户端套接字
  • buf是接受数据的缓冲区,len是缓冲区的大小
  • flags一般为0
  • 后面两个参数是用来获取:数据发送端的IP地址和端口号

sendto()

函数原型如下:

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

if (sendto(sockfd_c, buf, strlen(buf)+1, 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
            perror("sendto");
            continue;
        }

特别注意:

  • sockfd是本地套接字的描述符,在发送的时候一般要绑定本地套接字与众所周知的IP地址和端口
  • 参数中的套接字地址就是要发送的目的

示例

server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>

#define SERVER_IP "172.17.44.154"
#define SERVER_PORT 5002
#define BUFFERSIZE 100

int main(int argc, const char *argv[])
{
    int  sockfd_s;
    struct sockaddr_in server_addr, client_addr;
    char buf[BUFFERSIZE];  
    socklen_t addrlen;

    /* 创建套接字 */
    if ((sockfd_s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("socket");
        exit(-1);
    }

    /* 绑定服务器套接字 */
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_family = AF_INET;
    if (inet_pton(AF_INET, SERVER_IP, (void*)&server_addr.sin_addr.s_addr) != 1) {
        perror("inet_pton");
        exit(-1);
    }
    if (bind(sockfd_s, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        exit(-1);
    }
    
    while (1) {

        bzero(buf, BUFFERSIZE);
        if (recvfrom(sockfd_s, buf, BUFFERSIZE, 0, (struct sockaddr*)&client_addr, &addrlen) == -1) {
            perror("recvfrom");
            continue;       //UDP无连接传输,偶尔传输失败一次继续执行
        } else {            //成功收到
            if (strcmp(buf, "quit") == 0) {
            printf("the client %s/%d is quit\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
            exit(0);
            }
            printf("recv from %s/%d  data:%s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buf);

            sendto(sockfd_s, buf, strlen(buf)+1, 0, (struct sockaddr*)&client_addr, (socklen_t)sizeof(client_addr));      //retroreflection
        }
        
    }

    return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>


#define SERVER_IP "172.17.44.154"
#define SERVER_PORT 5002
#define BUFFERSIZE 100

int main(int argc, const char *argv[])
{
    int  sockfd_c;
    struct sockaddr_in server_addr;
    char buf[BUFFERSIZE];   //512
    socklen_t addrlen;
    /* 创建套接字 */
    if ((sockfd_c = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("socket");
        exit(-1);
    }

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_family = AF_INET;
    if (-1 == inet_pton(AF_INET, SERVER_IP, (void*)&server_addr.sin_addr.s_addr)) {
        perror("inet_pton");
        exit(-1);
    }
    
    while (1) {

        bzero(buf, BUFFERSIZE);
        printf("input:");         
        fgets(buf, BUFFERSIZE-1, stdin);

        if (sendto(sockfd_c, buf, strlen(buf)+1, 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
            perror("sendto");
            continue;
        }
        if (strcmp(buf, "quit\n") == 0) {
            printf("the client will quit\n");
            exit(0);
        }

        bzero(buf, BUFFERSIZE);
        // bzero(&server_addr, sizeof(server_addr));
        if (-1 == recvfrom(sockfd_c, buf, BUFFERSIZE - 1, 0, (struct sockaddr*)&server_addr, &addrlen)) {
            perror("recvfrom");
            continue;
        }
        else {
            printf("recv from %s/%d  data:%s\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port), buf);
        }
        
    }
    
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值