TCP和UDP
什么是TCP
TCP即传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通讯协议。
TCP是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。
互联网与单个网络有很大的不同,因为互联网的不同部分可能有截然不同的拓补结构、带宽、延迟、数据包大小和其他参数。TCP的设计目标是能够动态地适应互联网的这些特性,而且具备面向各种故障的健壮性。
不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受计算连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传输给IP层,有它来通过网络将包传送给接收端实体的TCP层。
TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后
接收端实体对已成功接收到的包回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未接收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来校验数据是否有误;在发送和接收时都要计算校验。
每台支持TCP的机器都有一个TCP传输实体。TCP 实体可以时一个库过程、一个用户进程、或者内核的一部分。在所有这些情形下,它管理TCP流,以及与IP层之间的接口。TCP传输实体接收本地进程的用户数据流,将他们分割成不超过64KB(实际上去掉IP和TCP头,通常不超过1460数据字节)的分段,每个分段以单独的IP数据报形式发送。当包含TCP数据的数据报到达一台机器时,它们被递交给TCP传输实体,TCP传输实体重构出原始的字节流。为简化起见,我们有时候仅仅用TCP来代表TCP传输实体(一段软件)或者TCP协议(一组规则)。根据上下文语义你应该能很清楚的推断出其实际含义。例如,在‘用户将数据提交给TCP’这句话中,很显然这里指的时TCP实体。
IP层并不保证数据报一定被正确的提交到接收方,也不只是数据报的发送速度有多块。正是TCP负责纪要足够快的发送数据报,以便使用网络容量,但又不能引起网络阻塞:而且,TCP超时后,要重传没有递交的数据报。即使被正确递交的数据报,也可能存在错误的问题,这也是TCP的责任,它必须把接收到的数据报重新装配成正确的顺序,简言之,TCP必须提供可靠性的良好性能,这正是大多数用户所期望的而IP又没有提供的功能。
用JAVA实现一个基于TCP的简单网络通信
创建TCP
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPTest1 {
@Test//客户端
public void client(){
Socket socket = null;
OutputStream os = null;
try {
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
socket = new Socket(inetAddress,8899);
os = socket.getOutputStream();
os.write("Nihao".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void server(){
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
serverSocket = new ServerSocket(8899);
socket = serverSocket.accept();
is = socket.getInputStream();
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[5];
int len;
while ((len = is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println("收到来自:"+socket.getInetAddress().getHostAddress()+"的数据");
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(baos!=null){
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(socket!=null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(serverSocket!=null){
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这段代码实现了基于TCP协议的简单网络通信,包括一个客户端和一个服务器端。具体来说,客户端通过建立Socket对象连接到指定的IP地址和端口号,将字符串"Nihao"以字节形式发送给服务器端。服务器端通过创建ServerSocket对象并绑定到指定的端口号,接受客户端的连接请求,然后获取输入流并读取客户端发送的数据,最后输出该数据的内容并关闭相关的资源。
什么是UDP
UDP 的英文单词是User Datagram Protocol,缩写为UDP
UDP是一种用户数据报协议,又成为用户数据报文协议,是一种报文的协议,不是面向连接的协议,TCP是基于连接的
是一个简单的面向数据报的传输层协议,正式规范为RFC 768
用户数据协议、非连接的协议,UDP的发起和接受是不需要经过连接的
仅仅只需要发送在对应端口上进行监听接受即可,不需要两个客户端一定是连接的
TCP和UDP的最大区别是什么呢?TCP是面向连接的,TCP是传输可靠的,UDP是面向数据报的,UDP是不可靠的,
不可靠的原因有三点:
1、它一但把数据发送给网络的数据发送出去,就不保留备份数据
2、在udp的数据层面,只管发送或者是接受数据,而不对这个数据进行保存备份重发等等
3、UDP在IP数据报的头部仅仅加入了复用和数据校验
4、发送端生产数据、接受端从网络中抓取数据,发送的时机和抓取的时机不想等,可能会导致客户端发送的数据服务器端没有接受到,在udp 中其实是没有标准的客户端和服务器端的,
5、UDP结构简单,无校验,速度快,容易丢包、可广播
UDP能做什么事情呢?
1、DNS、TPTP、SNMP
2、视频、音频、普通数据(无关紧要的数据),直播或者是有线电视,下载使用的TCP
3、0到16位存储的是发送源的IP地址,后面的16位存储的是咋们接受的ip地址,在前面16位后面存储的是发送的字节长度,紧跟着是头部和校验字段,0到16位是两个字节 也就是个短整形,端口是0到65535,用一个短整形来存储后面的数据部分,发送一个udp究竟能够带多大的数据出去呢?16位两个字节 + 自身协议64位 8个字节 最大能发送的数据是65507,当发送的数据大于65507 字节的时候,要做一次分包,
用JAVA实现一个基于UDP的网络通信
import org.junit.Test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPTest {
//发送端
@Test
public void sender() throws IOException {
DatagramSocket socket = new DatagramSocket();
String str = "我是UDP方式发送的导弹";
byte[] data = str.getBytes();
InetAddress inet = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9090);
socket.send(packet);
socket.close();
}
//接收端
@Test
public void receiver() throws IOException {
DatagramSocket socket = new DatagramSocket(9090);
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
socket.close();
}
}
这段代码实现了基于UDP协议的网络编程,包括一个发送端和一个接收端。具体来说,发送端通过创建DatagramSocket对象,将字符串"我是UDP方式发送的导弹"转换成字节数组,并封装成DatagramPacket对象,指定目标主机的IP地址和端口号,然后通过send()方法将数据包发送出去。接收端通过创建DatagramSocket对象,指定一个端口号并监听该端口,通过创建一个DatagramPacket对象,接收从网络上接收到的数据包,并将其转换成字符串输出到控制台。