一.什么是TCP?
TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议(“面向连接”就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了、对方拿起话筒才能相互通话。)也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,我们这里只做简单、形象的介绍,你只要做到能够理解这个过程即可。我们来看看这三次对话的简单过程:主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;主机B向主机
A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠性要求高的数据通信系统往往使用TCP协议传输数据。
优点: 可靠,稳定,TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
缺点: 慢,效率低,占用系统资源高。
二.什么是UDP?
优点:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多。
缺点:不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。
以下所有代码都是测试方法。
@Test
public void inetAddress() throws UnknownHostException {
// 127.0.0.1 回送地址 本机
InetAddress inet=InetAddress.getByName("127.0.0.1");
System.out.println(inet.getHostName());
}
TCP
客户端:
1.构建Socket实例,通过指定的远程服务器地址和端口来建立连接。
2.通过Socket实例包含的InputStream和OutputStream来进行数据的读写。
3.操作结束后调用socket实例的close方法,关闭。
服务端
1. 构建一个ServerSocket实例,指定本地的端口。这个socket就是用来监听指定端口的连接请求的。
2调用socket的accept()方法来获得下面客户端的连接请求。通过accept()方法返回的socket实例,建立了一个和客户端的新连接。
3通过这个返回的socket实例获取InputStream和OutputStream,可以通过这两个stream来分别读和写数据。
4结束的时候调用socket实例的close()方法关闭socket连接。
//客户端
@Test
public void client() {
String str="123";
//创建客户端的socket服务。
Socket s = null;
// 输出流
OutputStream os = null;
// 输入流
InputStream is = null;
try {
// 指定目的主机和端口 端口号范围:0-65535
s=new Socket("192.168.0.56",8888);
os=s.getOutputStream();
//写出数据
os.write(str.getBytes());
s.shutdownOutput();
//接收数据
is = s.getInputStream();
byte[] b=new byte[1024];
int len;
StringBuilder sb=new StringBuilder();
while((len=is.read(b))!=-1) {
sb.append(new String(b, 0, len));
}
System.out.println(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e2) {
e2.printStackTrace();
}
try {
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//服务端
@Test
public void TCPserver() {
//建立服务端socket服务。并监听一个端口。
ServerSocket ss = null;
InputStream is = null;
OutputStream os = null;
Socket accept = null;
try {
// 创建服务端
ss=new ServerSocket(8888);
// 接收客户端的连接
accept = ss.accept();
is = accept.getInputStream();
byte[] b=new byte[1024];
int len;
StringBuilder sb=new StringBuilder();
while((len=is.read(b))!=-1) {
sb.append(new String(b, 0, len));
}
// 打印
System.out.println(sb.toString());
//输出
os = accept.getOutputStream();
os.write("你好".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
accept.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP
服务端
1. 构造DatagramSocket实例,指定本地端口。
2. 通过DatagramSocket实例的receive方法接收DatagramPacket.DatagramPacket中间就包含了通信的内容。
3. 通过DatagramSocket的send和receive方法来收和发DatagramPacket.
客户端
1. 构造DatagramSocket实例。
2.通过DatagramSocket实例的send和receive方法发送DatagramPacket。
3.结束后,调用DatagramSocket的close方法关闭。
@Test
public void udpServer() {
Scanner sc=new Scanner(System.in);
try {
// 创建一个服务端DatagramSocket,指定一个监听的端口
DatagramSocket ds = new DatagramSocket(6789);
DatagramPacket dp;
while(true){
// 存储接收的数据
byte[] b=new byte[1024];
//数据包
dp=new DatagramPacket(b, b.length);
//接收
ds.receive(dp);
// 获取数据长度
int len=dp.getLength();
System.out.println(new String(b,0,len));
// 通过数据包获取地址
InetAddress byName = dp.getAddress();
String str=sc.nextLine();
// 要发送放入数据
byte[] b1=str.getBytes();
//把数据,目标地址,端口封装成一个DatagramPacket
dp=new DatagramPacket(b1, b1.length,byName,9876);
// 发送
ds.send(dp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void udpClient() {
Scanner sc=new Scanner(System.in);
try {
DatagramSocket ds = new DatagramSocket(9876);
DatagramPacket dp;
InetAddress byName = InetAddress.getByName("127.0.0.1");
while(true) {
String str=sc.nextLine();
// 要发送的数据
byte[] b=str.getBytes();
//把数据,目标地址,端口封装成一个DatagramPacket
dp=new DatagramPacket(b, b.length,byName,6789);
// 发送
ds.send(dp);
// 用于存储接收的数据
byte[] b2=str.getBytes();
// 数据包
dp=new DatagramPacket(b2, b2.length);
// 接收
ds.receive(dp);
// 获取数据长度
int len=dp.getLength();
System.out.println(new String(b,0,len));
}
} catch (Exception e) {
e.printStackTrace();
}
}