基本UDP套接口编程.doc_第1页
基本UDP套接口编程.doc_第2页
基本UDP套接口编程.doc_第3页
基本UDP套接口编程.doc_第4页
基本UDP套接口编程.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基本UDP套接口编程.txt爱情是艺术,结婚是技术,离婚是算术。这年头女孩们都在争做小“腰”精,谁还稀罕小“腹”婆呀?高职不如高薪,高薪不如高寿,高寿不如高兴。基本UDP套接口编程 - 第八军团 时间:2004-1-17 21:32:27 概述UDP无连接的 connectionless不可靠的 unreliable数据报协议 datagram应用:DNS, NFS, SNMP, ICQTCP面向连接的 connection-oriented可靠的 reliable字节流协议 byte stream应用:www, telnet ,ftp-UDP 客户-服务器程序的套接口函数recvfrom 和 sendto 函数#include ssize_t recvfrom(int sockfd, void *buff, size nbytes, int flags, struct sockaddr *from, socklen_t *addrlen);sockfd: 描述字buff: 指向输入缓冲器的指针nbytes: 读字节大小flag: 标志:0from :对方协议地址addrlen: 对方协议地址长度函数返回值: 读入数据的长度,可以为0.ssize_t sendto(int sockfd, void *buff, size nbytes, int flags, const struct sockaddr *to, socklen_t *addrlen);TCP的字节流输入输出函数:ssize_t readn(int sockfd, void *buff, size nbytes) ; ssize_t writen (int sockfd, void *buff, size nbytes);-UDP回射服务器程序/服务器main主程序#include unp.hInt main(int argc, char *argv)int sockfd; /定义套接字struct sockaddr_in servaddr, cliaddr; /IPv4套接口地址定义sockfd = Socket(AF_INET, SOCK_DGRAM, 0); /建立UDP套接字bzero(&servaddr, sizeof(servaddr); /地址结构清零servaddr.sin_family = AF_INET; /IPv4协议servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/内核指定地址servaddr.sin_port = htons(SERV_PORT); /9877 端口/*分配协议地址,绑定端口*/Bind(sockfd, (SA *) &servaddr, sizeof(servaddr); /* 回射子程序*/dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr);回射子程序:include unp.hvoid dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)int n; /读入字节数socklen_t len; /协议地址长度, 没有这个参数用 clilen也可以char mesgMAXLINE;for ( ; ; ) len = clilen;/* 读入一行 */n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);/* 回射到对方套接口 */Sendto(sockfd, mesg, n, 0, pcliaddr, len);-UDP回射客户程序/客户 main主程序include unp.hint main(int argc, char *argv) /命令行的第二个参数代表服务器地址 int sockfd; /套接字struct sockaddr_in servaddr; /服务器地址结构/* 必须在命令行指定服务器地址*/if (argc != 2) err_quit(usage: udpcli );bzero(&servaddr, sizeof(servaddr); /地址结构清零servaddr.sin_family = AF_INET; /IPv4servaddr.sin_port = htons(SERV_PORT); /9877端口/*网络字节序的IP地址*/Inet_pton(AF_INET, argv1, &servaddr.sin_addr); /*建立UPD套接口*/sockfd = Socket(AF_INET, SOCK_DGRAM, 0);/*回射客户端子程序, stdin 为标准输入:键盘*/dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr);exit(0); /子程序结束后退出程序/客户端回射子程序#include unp.hvoid dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)int n; /读入字节数char sendlineMAXLINE, recvlineMAXLINE + 1; / 1:结束标志占用/* 从键盘读入一行 */while (Fgets(sendline, MAXLINE, fp) != NULL) /如果不是D结束/* 将读入行发送到服务器套接口*/Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);/*从读入回射,读入字节数为n, 不关心从何处读入n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);recvlinen = 0; /* recvline字符串的结束标志*/Fputs(recvline, stdout); /输出到标准输出:显示器 /while循环结束:直到从键盘读入结束符D为止-验证收到的响应void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)int n; socklen_t len;char sendlineMAXLINE, recvlineMAXLINE + 1;struct sockaddr *preply_addr; /对方 (回应)地址指针preply_addr = Malloc(servlen); /分配地址结构while (Fgets(sendline, MAXLINE, fp) != NULL) Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);len = servlen; /* 读入一行,并获得对方的套接口地址*/n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);/*对方套接口地址长度和指定服务器地址长度不相同*/*或套接口地址结构也不相同时,*/if (len != servlen | memcmp(pservaddr, preply_addr, len) != 0) printf(“reply from %s (ignored)n”, /忽略回射行,并输出对方地址Sock_ntop(preply_addr, len) ); continue; /下一轮循环recvlinen = 0; /* null terminate */Fputs(recvline, stdout);-服务器进程未运行回射服务器-客户端程序执行的基本步骤:启动服务器启动客户程序服务器没有启动,客户端没有回射行,一直等待用tcpdump观察数据包 tcpdump icmp or arp or port 9877有ARP请求和应答:端口不可达 port . unreachable异步错误:由sendto 引起的ICMP错误, 而sendto本身并不返回该错误用已连接套接口才能返回到UDP套接口,需要调用connect.-UDP调用CONNECT在末连接UDP套接口上给两个数据报调用函数sendto导致内核执行下列六步:1.连接套接口;2.输出第一个数据报3.断开套接口连接;4.连接套接口,5.输出第二个数据报;6.断开套接口连接已连接套接口发送两个数据报的导致内核执行如下步骤;1.连接套接口;2.输出第一个数据报;3.输出第二个数据报。对同一套接口发送时,耗时减少1/3-dg_cli 函数(修订版)调用connect 函数(有ICMP错误返回)用read和write代替sendto 和 recvform/* 调用connect函数的UDP 回射客户子程序*/void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)int n;char sendlineMAXLINE, recvlineMAXLINE + 1;/* 与对方建立连接 */Connect(sockfd, (SA *) pservaddr, servlen);while (Fgets(sendline, MAXLINE, fp) != NULL) Write(sockfd, sendline, strlen(sendline);n = Read(sockfd, recvline, MAXLINE);recvlinen = 0; /* null terminate */Fputs(recvline, stdout);-UPD缺乏流量控制UDP没有流量控制,它是不可靠的。如果UDP发送方比UDP接收方运行速度快, 可能导致接收缓冲区满而造成数据报丢失。对服务器或客户来说,并没有给出任何指示说这些数据报已丢失。UDP套接口缓冲区由UDP给特定套接口排队的UDP数据报数目受限于套接口接收缓冲区的大小。用SO_RCVBUF套接口选项改变此值,可以改善数据报丢失的情况,但并不能从根本上解决问题。/*增大套接口接收队列大小的函数*/static void recvfrom_int(int); /内部函数static int count;void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)int n; socklen_t len;char mesgMAXLINE;Signal(SIGINT, recvfrom_int);n = 240 * 1024;Setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n);for ( ; ; ) len = clilen;Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);count+;static void recvfrom_int(int signo) printf(nreceived %d datagramsn, count);exit(0);-UDP中外出接口的确定已连接UDP套接口可用来确定用于待定目标的外出接口。内核选择本地IP地址(假设进程并没有调用bind以明确地指派它)。这个本地IP地址是通过给目的IP地址按索路由表,然后使用结果接口的主IP地址而选定的。例程:int main(int argc, char *argv)int sockfd;socklen_t len;struct sockaddr_in cliaddr, servaddr;if (argc != 2) err_quit(usage: udpcli );sockfd = Socket(AF_INET, SOCK_DGRAM, 0);bzero(&servaddr, sizeof(servaddr);servaddr.sin_family = AF_INE

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论