概念层面:

Udp的特点:1.udp是无连接的2.udp是尽最大努力交付3.udp是面向报文的4.udp没有拥塞控制5.udp支持一对一,一对多,多对一或多对多的交互通信6.udp的首部开销小(8比特)

Tcp的特点:1.tcp是面向连接的运输层协议2.tcp连接只能是点对点3.tcp是可靠交付的4.tcp是全双工通信5.tcp是面向字节流的

网络编程层面

      Tcp编程需要三次握手,具体细节为:

1.int socket(int domain, int type, int protocal); 函数调用成功返回套接字标识符(内核创建了一个套接字数据结构),失败返回-1,并设置error

2.int bind(int sockfd,struct sockaddr *my_addr,int addrlen); 主要是通过套接字实现应用程序与内核的交互,bind函数得到套接字描述符,将套接口与一定的端口号相连接(my_addr中的内容),该绑定过程需注意网络字节顺序(大段)与主机字节顺序(小段)

3.int listen(int sockfd,int backlog);将套接字转换成被动侦听套接字,并在套接字指定的端口上开始侦听,侦听队列(大多数系统默认缺省值20,一般设置成5~10),实际上队列上侦听的请求应该是backlog的1.5倍

4.int accept(int sockfd, struct sockaddr *addr, int *addrlen); 成功返回一个新的套接字描述符,不同于倾听套接字(只用于接受客户端进程的连接,是为完成三次握手而用的),用来标识一个TCP连接

5.int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); serv_addr   用于指定远程服务器的IP地址与端口号,

6.int close(int sockfd); 关闭套接字描述符。

客户端只有socket()àconnect()à…..-->close()

UDP数据报

服务器方面:int socket(int domain, int type, int protocal);

int bind(int sockfd,struct sockaddr *my_addr,int addrlen);

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr* from, int *fromlen);

int sendto(int sockfd, void *msg, int len, unsigned int flags, struct sockaddr *to, int tolen);

由于UDP是提供的是不可靠的服务,系统没有为udp套接字设置发送缓冲区,sendto 只是将数据从应用缓冲区复制到系统缓冲区,然后返回,之后的工作由UDP协议来完成,udp协议将这些数据封装成数据报,并将数据报交给较底层的IP协议,由IP协议来完成udp数据报的发送。参数from 中存储了接收到的数据报的源地址,to 中保存的是要发往的地址,因为是非连接的,所以在套接字的数据结构中没有记录接受者的信息,需要将其记录在to中;当应用程序调用函数recvfrom()接受数据时,UDP协议将返回一个完整的数据报

缓冲区问题

      进程创建每一个TCP套接字时还附带创建了一个套接字接收缓冲区和发送缓冲区(由套接字缓冲区转到系统缓冲区,随即往网络读写数据的过程是由内核TCP协议完成的),read()函数只完成从套接字缓冲区到应用进程缓冲区的数据读取(即一个系统调用过程,从网络中到套接字缓冲去由内核操作)

      read()函数读取时如果套接字缓冲区的数据量小于期望读取的数据量时,直接返回全部;大于时,返回len个;没有数据时,函数read()阻塞;

      write()函数,如果套接字缓冲区可用空间不足以存放所期望写的数据量时,write()函数将阻塞,等待套接字缓冲区有足够的空间,write()函数成功返回时,只能说明数据在缓冲区里,而不能说明已在网络中

      UDP:

#include<sys/socket.h>

Int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

Int sendto(int sockfd, void *buf, int len, unsigned int flags, struct socaddr *to, int tolen);

UDP协议为每个UDP套接字设置了一个接受缓冲区队列,当一个数据报到达时,协议将根据这个数据报的目的端口号,将它存放在相应的UDP套接字的接受缓冲区队列,调用recvfrom()函数从套接字缓冲区队列接受一个数据时,Linux操作系统核心将返回队列第一个数据报,函数返回值是这个数据报的长度大小,当缓冲队列为空时,函数将阻塞;如果套接字缓冲区队列满时,UDP协议将丢弃这个数据报,并且不向返送者返回任何错误信息,符合UDP协议不保证数据的可靠传输;