1、UDP常用的发送和接收函数
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); int sendto(int sockfd,const void *msg,int len,unsigned int flags,struct sockaddr *to,int tolen);
sockfd,buf,len的意义和read,write中的参数是一样的,分别表示套接字描述符,发送或接收的缓冲区及大小。
recvfrom负责从sockfd接收数据,如果from不是NULL,那么在from里面存储了信息来源的情况,如果对信息的来源不感兴趣,可以将from和fromlen设置为NULL。
sendto负责向to发送消息,此时在to里面存储了信息接收方的详细资料。
2、实例演示
服务端程序
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <arpa/inet.h> #define SERVER_PORT 8888 #define MAX_MSG_SIZE 1024 void udps_respon(int sockfd) { struct sockaddr_in addr; int n; socklen_t addrlen; char msg[MAX_MSG_SIZE]; while (1) { /* 从网络上读,写到网络上面去 */ memset(msg, 0, sizeof(msg)); addrlen = sizeof(struct sockaddr); n = recvfrom(sockfd, msg, MAX_MSG_SIZE, 0, (struct sockaddr*)&addr, &addrlen); /* 显示服务端已经收到了信息 */ fprintf(stdout, "I have received %s", msg); sendto(sockfd, msg, n, 0, (struct sockaddr*)&addr, addrlen); } } int main(void) { int sockfd; struct sockaddr_in addr; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd<0) { fprintf(stderr, "Socket Error:%s\n", strerror(errno)); exit(1); } bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(SERVER_PORT); if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))<0) { fprintf(stderr, "Bind Error:%s\n", strerror(errno)); exit(1); } udps_respon(sockfd); close(sockfd); }
客户端程序
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <arpa/inet.h> #define MAX_BUF_SIZE 1024 void udpc_requ(int sockfd, const struct sockaddr_in *addr, socklen_t len) { char buffer[MAX_BUF_SIZE]; int n; while (fgets(buffer, MAX_BUF_SIZE, stdin)) { /* 从键盘读入,写到服务端 */ sendto(sockfd, buffer, strlen(buffer), 0, addr, len); bzero(buffer, MAX_BUF_SIZE); /* 从网络上读,写到屏幕上 */ memset(buffer, 0, sizeof(buffer)); n = recvfrom(sockfd, buffer, MAX_BUF_SIZE, 0, NULL, NULL); if (n <= 0) { fprintf(stderr, "Recv Error %s\n", strerror(errno)); return; } buffer[n] = 0; fprintf(stderr, "get %s", buffer); } } int main(int argc, char **argv) { int sockfd, port; struct sockaddr_in addr; if (argc != 3) { fprintf(stderr, "Usage:%s server_ip server_port\n", argv[0]); exit(1); } if ((port = atoi(argv[2]))<0) { fprintf(stderr, "Usage:%s server_ip server_port\n", argv[0]); exit(1); } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd<0) { fprintf(stderr, "Socket Error:%s\n", strerror(errno)); exit(1); } /* 填充服务端的资料 */ bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(port); if (inet_aton(argv[1], &addr.sin_addr)<0) { fprintf(stderr, "Ip error:%s\n", strerror(errno)); exit(1); } if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1) { fprintf(stderr, "connect error %s\n", strerror(errno)); exit(1); } udpc_requ(sockfd, &addr, sizeof(struct sockaddr_in)); close(sockfd); }
写代码是一种艺术,甚于蒙娜丽莎的微笑。