无论发多大的包,IP层和链路层都会把你的包进行分片发送,一般局域网就是1500左右,广域网就只有几十字节。分片后的包将经过不同的路由到达接收方,对于UDP而言,要是其中一个分片丢失,那么接收方的IP层将把整个发送包丢弃,这就形成丢包
头文件
#include <sys/types.h>
#include <sys/socket.h>
函数原型
int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen); int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
server
/************************************************************************* > File Name: server.c > Author: Chen > Mail: 971859774@qq.com > Created Time: 2018年11月12日 星期一 21时30分34秒 ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <string.h> #include <strings.h> #include "my_err.h" #define SERV_PORT 9877 void dg_ser(int sockfd,struct sockaddr * cliaddr,socklen_t clilen) { char msg[MAXLINE]; memset(msg,sizeof(msg),0); int index=0; while(1) { socklen_t len=clilen; int n=recvfrom(sockfd,msg,MAXLINE,0,cliaddr,&len); char m[len]; printf("server receive from %s, message: %s",inet_ntop(AF_INET,cliaddr,m,len),msg); sendto(sockfd,msg,n,0,cliaddr,len); } return; } int main(int argc,char **argv) { int sockfd=socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in servaddr,cliaddr; bzero(&servaddr,sizeof(servaddr)); servaddr.sin_port=htons(SERV_PORT); servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY); bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); char msg[sizeof(servaddr)]; printf("server adress: %s ",inet_ntop(AF_INET,(struct sockaddr *)&servaddr,msg,sizeof(servaddr))); dg_ser(sockfd,(struct sockaddr *)&cliaddr,sizeof(cliaddr)); return 0; }
调用connect的client
/************************************************************************* > File Name: client.c > Author: Chen > Mail: 971859774@qq.com > Created Time: 2018年11月12日 星期一 20时47分06秒 ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <strings.h> #include "my_err.h" #define SERV_PORT 9877 void dg_cli(int sockfd,const struct sockaddr* servaddr,socklen_t servlen) { char sendline[MAXLINE],recvline[MAXLINE+1]; //调用connect的udp套接字 int res=connect(sockfd,(struct sockaddr *)servaddr,servlen); if(res<0) { fprintf(stderr,"connect error "); exit(0); } /*利用connect确定外出接口,因为connect udp套接字的时候,内核自动选 *(假设未显示调用bind),本地ip地址通过为目的ip地址搜索路由表得到的 *外出借口,然后选用该接口的主ip地址而选定 */ struct sockaddr_in cliaddr; socklen_t len=sizeof(cliaddr); getsockname(sockfd,(struct sockaddr *)&cliaddr,&len); char m[len]; printf("local address: %s ",inet_ntop(AF_INET,(struct sockaddr *)&cliaddr,m,len)); while(fgets(sendline,MAXLINE,stdin)!=NULL) { /* * 如果此时服务器未启动,客户将永远阻塞在recvfrom中。 * 愿意:在客户像服务器发送udp数据报之前,先进行一次arp的请求答应 * 交换,这个 请求交换放在tcpdump中输出中,服务器相应一个端口不可 * 达错误,这也成为异步错误,该错误有sendto引起,但sendto却成功返回 * ,udp输出操作成功返回仅仅表示接口接口队列中具有存放形成的ip数据 * 报的空间,对于udp套接字,由它引发的错误却不返回给他 */ size_t fw=write(sockfd,sendline,strlen(sendline)); if(fw<0) { fprintf(stderr,"write error "); exit(0); } size_t n=read(sockfd,recvline,MAXLINE); char *msg=strerror(errno); if(errno==111) { fprintf(stderr,"%s ",msg); exit(1); } if(n<0) { fprintf(stderr,"read error "); } recvline[n]='