發送端:socket
#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包是完整的、順序正確的。請在接收端使用抓包工具驗證。ui