Linux下udp编程
一、函数
1、recvfrom函数
UDP使用recvfrom()函数接收数据,他类似于标准的read(),但是在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); //返回发送数据的长度 -非0成功 -1-失败
2、sendto函数
UDP使用sendto()函数发送数据,他类似于标准的write(),但是在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); //返回发送数据的长度 -非0成功 -1-失败
3、socket函数
#include <sys/types.h> #include <sys/socket.h> //函数原型 int socket(int domain, int type, int protocol);
为了执行网络输入输出,一个进程必须做的第一件事就是调用socket函数获得一个文件描述符。
第一个参数指明了协议簇,目前支持5种协议簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议)。
第二个参数指明套接字类型,有三种类型可选:SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和SOCK_RAW(原始套接口);TCP一般选择SOCK_STREAM,而UDP选择SOCK_DGRAM。
4、bind函数
#include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第一个参数是socket函数返回的套接字的文件描述符。第二和第三个参数分别是一个指向特定于协议的地址结构的指针和该地址结构的长度。
5、sockaddr_in
#include <netinet/in.h>
#include <arpa/inet.h>
struct sockaddr_in { sa_family_t sin_family; //地址族(Address Family) uint16_t sin_port ; //16位 TCP/IP 端口号 struct in_addr sin_addr; //32位 IP 地址 char sin_zero[8]; };
二、server.c 测试代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netinet/ip.h> #include<unistd.h> #include<arpa/inet.h> #include <sys/time.h> #include <unistd.h> #define UDP_PORT 8080 #define UDP_BUF_SIZE 100 #define UDP_SERV_IP_ADDR "192.168.100.178" #define UDP_CLIENT_IP_ADDR "192.168.100.51" int main(void) { int fd = -1; int len = 0; int res = 0; int i; struct sockaddr_in sin; /* 创建socket_fd */ if((fd = socket( AF_INET, SOCK_DGRAM , 0)) < 0) { printf("*******SOCKET********\n"); return -1; } /* 允许绑定地址快速重用 */ int b_reuse = 1; setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(b_reuse)); /* 填充struct sockaddr_in 结构体变量 */ bzero( &sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(UDP_PORT); /* 让服务器程序能绑定在任意的IP上 */ #if 1 sin.sin_addr.s_addr = htonl(INADDR_ANY);//绑定任何主机上ip地址 #else if((inet_pton(AF_INET, UDP_SERV_IP_ADDR, (void *)&sin.sin_addr)) < 0) { printf("******INET_PTON*******\n"); return -1; } #endif /* 绑定 */ if(bind (fd, (struct sockaddr *)&sin, sizeof(sin)) <0 ) { printf("*******bind*******\n"); return -1; } char buf[UDP_BUF_SIZE]; struct sockaddr_in cin; socklen_t addrlen = sizeof(cin); while(1) { bzero(buf ,UDP_BUF_SIZE);
memset(buf,0,sizeof(buf));
len=0;
len = recvfrom(fd, buf, UDP_BUF_SIZE-1,0,(struct sockaddr*)&cin, &addrlen);
if(len > 0) { char ipv4_addr[16]; if(!inet_ntop(AF_INET, (void *)&cin.sin_addr, ipv4_addr, sizeof(cin))) { printf("*******inet_ntop********\n"); return -1; } printf("********recv from (%s:%d), date:",ipv4_addr, ntohs(sin.sin_port)); for(i = 0;i< len;i++) printf("%02X ", buf[i]); printf("\n"); }
sendto(fd,buf,len,0,(struct sockaddr*)&cin, addrlen); } close(fd); return 0; }