UNP卷1:第八章(基本UNP套接字编程)
来源:互联网 发布:单片机开发板能做什么 编辑:程序博客网 时间:2024/04/26 18:02
1. 简单的UDP回射程序
1) 服务器udpsrv.c
#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#define MAXLINE 1024#define SA struct sockaddrvoid dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen);int main(int argc, char **argv){intsockfd;structsockaddr_inservaddr, cliaddr;sockfd = socket(AF_INET, SOCK_DGRAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(9877);bind(sockfd, (SA *)&servaddr, sizeof(servaddr));dg_echo(sockfd, (SA *)&cliaddr, sizeof(cliaddr));return 0;}void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen){intn;socklen_tlen;charmesg[MAXLINE];for ( ; ; ){len = clilen;n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);sendto(sockfd, mesg, n, 0, pcliaddr, len);}}
2) 客户端udpcli.c
#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#define MAXLINE 1024#define SA struct sockaddrvoid dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen);int main(int argc, char **argv){intsockfd;structsockaddr_inservaddr;if (argc != 2){printf("argument should be 2\n");exit(-1);}bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(9877);inet_pton(AF_INET, argv[1], &servaddr.sin_addr);sockfd = socket(AF_INET, SOCK_DGRAM, 0);dg_cli(stdin, sockfd, (SA *)&servaddr, sizeof(servaddr));exit(0);}void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen){intn;charsendline[MAXLINE], recvline[MAXLINE + 1];while (fgets(sendline, MAXLINE, fp) != NULL){sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);recvline[n] = 0;fputs(recvline, stdout);}}
程序输入输出:
服务器:
leichaojian@ThinkPad-T430i:~$ ./udpsrv
客户端:
leichaojian@ThinkPad-T430i:~$ ./udpcli 127.0.0.1i love youi love you^C
3) 服务器进程未运行时候客户端的阻塞
如果服务器未启动而客户端发送一行文本,则客户永远阻塞于它的recvfrom调用,等待一个永不出现的服务器应答(所以下例中tcpdump只显示第一行hello world的信息,而其余的信息已经被阻塞了):
启动tcpdump:
root@ThinkPad-T430i:/home/leichaojian# tcpdump -i eth0 udp port 9877tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes22:18:50.481559 IP 192.168.0.7.60341 > 218.30.64.194.9877: UDP, length 12直接启动客户端:
leichaojian@ThinkPad-T430i:~$ ./udpcli 218.30.64.194hello worldi love youwhattcpdump只显示hello world发送的文本,而接着发送i love you和what则没有任何的反应,因为已经阻塞了。其中9877是服务器指定的总所周知的端口号,而60341为客户端临时端口。
2. UDP的connect函数
1) connect函数的起源
除非套接字已连接,否则异步错误是不会返回到UDP套接字的。我们可以给UDP套接字调用connect,然而这样做的结果却与TCP连接大相近庭:没有三次握手过程。内核只是检查是否存在立即可知的错误,记录对端的IP地址和端口号(取自传递给connect的套接字地址结构),然后立即返回到调用进程。
有了这个能力后,我们必须区分:
(1) 未连接UDP套接字,新创建UDP套接字默认如此。
(2) 已连接UDP套接字,对UDP套接字调用connect的结果。
对于已连接UDP套接字,与默认的未连接UDP套接字相比,发生了三个变化:
(1) 我们再也不能给输出操作指定目的IP地址和端口号。也就是说,我们不使用sendto而改用write或send。写到已连接UDP套接字上的任何内容都自动发送到由connect指定的协议地址(例如IP地址和端口号)
(2) 我们不必使用recvfrom以获悉数据报的发送者,而改用read,recv或recvmsg。在一个已连接UDP套接字上,由内核为输入操作返回的数据报只有那些来自connect所指定协议地址的数据报。目的地为这个已连接UDP套接字的本地协议地址(例如IP地址和端口号),发源地却不是该套接字早先connect到的协议地址的数据报,不会投递到该套接字。这样就限制一个已连接UDP套接字能且仅能与一个对端交换数据报。
(3) 由已连接UDP套接字引发的异步错误会返回给它们所在的进程,而未连接UDP套接字不接收任何异步错误。
2) 使用connect的客户端
#include "myunp.h"void dg_cli( FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen ){intn;charsendline[ MAXLINE ], recvline[ MAXLINE + 1 ];Connect( sockfd, ( SA * )pservaddr, servlen );while ( fgets( sendline, MAXLINE, fp ) != NULL ){write( sockfd, sendline, strlen( sendline ) );n = read( sockfd, recvline, MAXLINE );if ( n < 0 ){printf("read error\n");return;}recvline[ n ] = 0;fputs( recvline, stdout );}}int main( int argc, char **argv ){intsockfd;structsockaddr_inservaddr;bzero( &servaddr, sizeof( servaddr ) );servaddr.sin_family = AF_INET;servaddr.sin_port = htons( 9877 );inet_pton( AF_INET, argv[ 1 ], &servaddr.sin_addr );sockfd = Socket( AF_INET, SOCK_DGRAM, 0 );dg_cli( stdin, sockfd, ( SA * )&servaddr, sizeof( servaddr ) );exit( 0 );}
如果服务端不启动,则输出结果如下:
服务端:
root@ThinkPad-T430i:/home/leichaojian# tcpdump -i eth0 udp port 9877tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes19:27:08.010090 IP 192.168.0.7.51328 > 218.30.64.194.9877: UDP, length 12
客户端分两种情况:
1)
leichaojian@ThinkPad-T430i:~$ host leichaojianleichaojian.router has address 218.30.64.194Host leichaojian.router not found: 5(REFUSED)Host leichaojian.router not found: 3(NXDOMAIN)leichaojian@ThinkPad-T430i:~$ ./dgcliconnect 218.30.64.194hello world^C
2) 如果是以下的代码,则服务端无任何抓包行为:
leichaojian@ThinkPad-T430i:~$ ./dgcliconnect 127.0.0.1hello worldn is:-1read error
- UNP卷1:第八章(基本UNP套接字编程)
- UNP卷1:第三章(套接字编程简介)
- UNP卷1:第四章(基本TCP套接字编程)
- UNP学习笔记(第八章 基本UDP套接字编程)
- UNP卷一学习笔记:基本UDP套接字编程
- UNP学习:基本套接字编程
- UNP笔记(2)——基本套接字编程
- UNP卷一学习笔记:基本TCP套接字
- UNP学习笔记(第四章 基本TCP套接字编程)
- UNP学习笔记(第三章:套接字编程简介)
- UNP卷1:第二十章(广播)
- UNP函数笔记二: 基本TCP套接字编程
- UNP函数笔记六: 基本UDP套接字编程
- UNP函数笔记七: 基本SCTP套接字编程
- UNP总结 Chapter 4 基本TCP套接字编程
- UNP总结 Chapter 8 基本UDP套接字编程
- UNP总结 Chapter 4 基本TCP套接字编程
- UNP——Chapter 4:基本TCP套接字编程
- HDU 5037 FROG 贪心 2014北京网络赛F
- 数据倾斜总结
- android横竖屏切换周期
- [LeetCode] Sort List
- 我的编程学习日志(10)--求字符数组与数字数组的长度(strlen,,size,sizeof)
- UNP卷1:第八章(基本UNP套接字编程)
- 《数据结构》 实验2
- HDU5033
- 右键里面添加一个“打开终端”和更换gnome
- 《数据结构》第一章 知识点结构导图
- 线性表 第二章
- 2014.9.21
- js本地压缩图片,上传base64给后台,再给七牛
- Android从网络中获取图片