首页 > 技术文章 > linux udp c语言示例

jacob1934 2015-01-21 15:23 原文

发送端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main()
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0)
    {
        printf("socket() failed,%s\n",strerror(errno));
        return -1;
    }
    
    struct sockaddr_in addr =
    {
        .sin_family     = AF_INET,
        .sin_port     = htons(3355),
        .sin_addr.s_addr = inet_addr("192.168.1.100")//htonl(INADDR_ANY)    //
    };
    uint32_t count    = 1;
    while(1)
    {
        uint32_t buf[10240] = {0};
        buf[1] = count;
        buf[0] = 0x76543210;
        
        int ret = sendto(fd, buf, sizeof(buf), 0, 
            (struct sockaddr *)&addr, sizeof(addr));
        if(ret == (int)sizeof(buf))
        {
            
            printf("to %s:%d package %u send\n", 
                inet_ntoa(addr.sin_addr),
                htons(addr.sin_port),
                count);
        }
        else if(ret >= 0 && ret < (int)sizeof(buf))
        {
            printf("%d byte sended\n",ret);
        }
        else if(ret < 0)
        {
            printf("sendto failed,%s\n",strerror(errno));
        }
        count++;
        //usleep(10);
    }
    close(fd);
    return 0;
}

接收端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
void print_client_addr(struct sockaddr_in *client)
{
    printf("client %s:%d\t",
            inet_ntoa(client->sin_addr),
            ntohs(client->sin_port));
}
int main()
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0)
    {
        printf("socket() failed,%s\n",strerror(errno));
        return -1;
    }
    
    struct sockaddr_in addr =
    {
        .sin_family     = AF_INET,
        .sin_port     = htons(3355),
        .sin_addr.s_addr = htonl(INADDR_ANY)
    };
    bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    uint32_t serial = 0;
    while(1)
    {
        uint32_t buf[10240] = {0};
        
        struct sockaddr_in addr_client;
        socklen_t addr_len = sizeof(addr_client);
        
        int ret = recvfrom(fd, buf, sizeof(buf), 0, 
            (struct sockaddr *)&addr_client, &addr_len);
        
        if(ret >= 0)
        {
            
            if(ret < (int)sizeof(buf))
            {
                print_client_addr(&addr_client);
                printf("%d byte recved\n",ret);
            }
            else
            {
                if(buf[0] == 0x76543210)
                {
                    //print_client_addr(&addr_client);
                    //printf("package %d recved",buf[1]);
                    if(buf[1] != serial + 1)
                    {
                        print_client_addr(&addr_client);
                        printf("package from %u to %u lost\n",
                            serial + 1, buf[1] - 1);
                    }
                    //else
                        //printf("\n");
                    serial = buf[1];
                    
                }
                else
                {
                    print_client_addr(&addr_client);
                    printf("package %d head lost\n",serial);
                }
            }
        }
        else if(ret < 0)
        {
            printf("recvfrom failed,%s\n",strerror(errno));
        }
        
    }
    close(fd);
    return 0;
}

 在该示例中,直接使用sendto发送40KByte的数据,远远大于MTU的典型值1500,UDP包会被分成N个IPV4的封包,任何一个IPV4封包丢失都将导致UDP封包的丢失,但IP层能保证recvfrom()返回的UDP包是完整的、顺序正确的。请在接收端使用抓包工具验证。

推荐阅读