您的位置:首页 > 理论基础 > 计算机网络

《UNIX网络编程卷1》读书笔记--第八章基本UDP套接字编程

2017-03-24 11:40 399 查看

前言

本章简单介绍了UDP服务器程序的编写,到22.5节再讨论如何增加UDP程序的可靠性




关注点

recvfrom函数和sendto函数

UDP回射服务器程序

UDP回射客户端程序

采用UDP的缺点及改进措施

UDP的connect函数

使用select函数的TCP和UDP回射服务器程序

recvfrom函数和sendto函数

#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,
struct sockaddr *from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,
const struct sockaddr *to, socklen_t addrlen);


recvfrom像是accept和read的结合
但是中间多了一个flags参数,将在14章讨论recv、send、recvmsg函数时做介绍。本章都置为0.


UDP回射服务器程序

#include "unp.h"
void dg_echo(int , SA *, socklen_t);
int main(int argc, char const *argv[]) {
int sockfd;
struct sockaddr_in servaddr, cliaddr;

sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

Bind(sockfd, (SA*)&servaddr, sizeof(servaddr));

dg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr));
}

void dg_echo(int sockfd, SA * pcliaddr, socklen_t clilen){
int n;
socklen_t len;
char msg[MAXLINE];
for( ; ; ){
len = clilen;
n = Recvfrom(sockfd, msg, MAXLINE, 0, pcliaddr, &len);

Sendto(sockfd, msg, n, 0, pcliaddr, len);
}
}


UDP回射客户端程序

#include "unp.h"

void dg_cli(FILE *, int, const SA *, socklen_t);

int main(int argc, char const *argv[]) {

if(argc != 2)
err_quit("usage: ./udpcli01 <IPaddress>");

int sockfd;
struct sockaddr_in servaddr;

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

dg_cli(stdin, sockfd, (SA *)&servaddr, sizeof(servaddr));
}

void dg_cli(FILE * fp,int sockfd, const SA * servaddr, socklen_t servlen){
char buf[MAXLINE];
int n;
socklen_t len = servlen;
for( ; ; ){
if(Fgets(buf, MAXLINE, fp) == NULL)
return ;
else
Sendto(sockfd, buf, strlen(buf), 0, servaddr, servlen);
if((n = Recvfrom(sockfd, buf, n, 0, NULL, NULL)) == 0){
err_quit("connection close");
}
else if(n < 0)
err_quit("Recvfrom error");
buf
= 0;
Fputs(buf, stdout);
}
}


UDP服务端是一个典型的迭代器模型,大多数TCP服务器是并发的。对于本套接字,UDP层中隐含有排队发送,每个UDP套接字都有一个接收缓冲区,实行FIFO机制。


采用UDP的缺点及改进措施

1. 数据报丢失:
数据报丢失导致客户阻塞于recvfrom调用,可以设置超时机制解决,14.2节讨论。
2. 验证接收响应的确认:
从新malloc一个sockaddr *变量,在Recvfrom获得其值,比较该变量和原先发送的servaddr,相同就是需要的变量。
3. 服务器进程未运行
服务器主机响应“port unreachable”ICMP消息,但是此时的进程不能识别这个异步错误,它永远阻塞于recvfrom调用,我们需要用connect获取这个ICMP消息。


UDP的connect函数

1. connect只是绑定了目的IP和端口号,使得ICMP返回到指定的套接字
2. 与此同时,具有绑定端口号功能的sendto和recvfrom最好相应改为write和read
3. 多次调用connect可以更改目的端口号和IP或者断开套接字
4. 调用connect可以提高需要多次传输数据的UDP协议的性能(减少了内核中间连接、断开套接字的开销)


使用select函数的TCP和UDP回射服务器程序

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息