在计算机网络中,TCP和UDP是传输层中的两个重要的协议。TCP是传输控制协议,UDP是用户数据包协议。IP协议是网络层的重要协议,IP协议是支持网间互联的数据通信协议。
TCP/IP协议是一个高效的四层网络通信协议。两台主机要进行通信要遵守TCP/IP协议,两个主机上的程序要在网络上通信,必须要有对方主机的IP,有了IP才能找到要通信的另一台主机,找到了通信主机,还满足不了两台主机上的两个程序 之间的通信,因为找到了另一个通信的主机,并不能准确地把信息交给指定的程序去解析。所以还需要一个标识来确定另一台主机上的指定的一个程序,这个标识就叫做端口。在操作系统上运行的每一个程序都有自己的端口,用来让别的程序找到自己。
在java中,java语言对IP的描述封装成了一个类,叫做InetAddress。
在Java中,java语言把IP和端口抽象成了一个类,这个类就是Socket类:
Socket(InetAddress address, int port) |
这是Socket类的一个构造方法,可以把IP和端口封装成一个对象。有了这个对象,就可以找到指定主机的指定程序。就可以在网络上进行不同计算机上的两个程序的通信。
当我们知道了目标主机的IP和要通讯的程序的端口,就可以利用Scoket对象来进行通信。
Scoket对象提供了一个字节输出流(OutPutStream),这个输出流指向目标主机的指定端口。
当我们的程序对目标写出信息的时候,目标主机上的指定端口程序需要来检测我们的程序发来的信息。
怎么检测?
java语言提供了一个类可以标识本程序端口和检测Scoket写出的信息,并获取到这个Scoket。当目标主机获取到了这个Scoket就获取到了我们主机的IP和端口,目标主机程序就可以利用它得到的Scoket来给我们返回信息。
这个提供检测的类就叫做ServerScoket类。
下面是TCP通信的一个例子:
本机程序
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws Exception {
//把目标主机IP封装成InetAdress对象。
InetAddress targetIP = InetAddress.getByAddress(new byte[]{10,10,92,(byte)174});
//新建一个Socket对象封装IP和端口用来通信。
Socket so = new Socket(targetIP,9999);
//利用Scoket对象来获取字节输出流。
OutputStream targetOut = so.getOutputStream();
//定义一个字节数组用来存储要发送的数据
byte[] bt = "你好,我想联系你了".getBytes();
//读取数组数据并写出
targetOut.write(bt);
//利用Scoket对象获取字节输入流,来接收对方返回的信息
InputStream re = so.getInputStream();
//定义字节数组来存储收到的信息
byte[] rbt = new byte[1024];
//读取信息写入到数组,并记录读取长度
int len = re.read(rbt);
//把信息解码成字符串并打印
System.out.println(new String(rbt, 0, len));
//关流
targetOut.close();
re.close();
//关闭Scoket对象
so.close();
}
}
目标主机程序
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws Exception {
//新建一个检测对象,并标识自己的端口
ServerSocket sv = new ServerSocket(9999);
//监测Scoket对象并获取
Socket so = sv.accept();
//利用获取到的Scoket对象来获取输入流,
InputStream in = so.getInputStream();
//新建一个数组存储信息
byte[] by = new byte[1024];
//把信息读到数组里,并记录所读长度
int len = in.read(by);
//解析信息
System.out.println(new String(by, 0, len));
//获取输出流,返回回应
OutputStream f = so.getOutputStream();
//定义返回内容
byte[] bt = "你要相信,美好的事情即将发生。".getBytes();
//写出
f.write(bt);
//关流
in.close();
f.close();
sv.close();
}
}
通信前提是,目标主机已经运行程序后,本机后运行程序才能通信成功。
运行结果,目标主机接收到本机程序发送的字符串数据,本机收到目标主机程序返回的字符串信息。
UDP是一种不可靠传输,因为这个协议并不进行连接,直接发送数据,不面向连接。不管目标主机程序有没有运行都会进行发送。
UDP中利用数据包来发送和接收数据,数据包里包含了目标主机的IP和程序端口还有数据。
java中DatagramSocket用来描述发送和接收点(定义 发送或接收点的程序端口),并具有接收和发送数据包的功能。
DatagramPacket用来描述数据包。
以下是UDP通信的一个例子:
本机程序
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//本机的两个java程序利用UDP协议来传输内容(可以是各种文件,底层传输的是byte数组里的字节)
public class UDPSend {
public static void main(String[] args) throws Exception {
//第一步,获取目标主机的IP对象
InetAddress myIP = InetAddress.getLocalHost();
//InetAddress myIP = InetAddress.getByAddress(new byte[]{10,10,92,(byte)174});
//第二步,创建发送或接收点对象,可以指定本java发送程序在操作系统上运行的端口
//DatagramSocket类是java中UDP协议使用的,用来创建发送和接收点对象
//创建DatagramSocket对象,并设置本程序端口
DatagramSocket ds = new DatagramSocket(9999);
//第三步,把需要传输的内容封装到字节数组内
String str = "你好,我是客户端";
byte[] by = str.getBytes();
//第四步,创建发送包,包内存放字节数组(也就是传输的内容)和发送目标主机的IP和运行在目标主机上的Java接收程序端口
DatagramPacket pak = new DatagramPacket(by,0,by.length,myIP,8888);
//第五步,用发送或接收点对象发送 数据包
ds.send(pak);
//接收从服务器返回的信息
//创建接受数据的数组
byte[] byy= new byte[1024];
//创建数据包,用来存放字节数组
DatagramPacket packet = new DatagramPacket(byy, byy.length);
//接收返回信息
ds.receive(packet);
//把包中内容解析成字符串并打印
System.out.println(new String(packet.getData(), 0,packet.getData().length));
//关闭数据点
ds.close();
}
}
目标主机程序:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//本机的两个java程序利用UDP协议来传输内容(可以是各种文件,底层传输的是byte数组里的字节)
public class UDPReceive {
public static void main(String[] args) throws Exception {
//创建接收点对象,并定义此java程序的端口
DatagramSocket ds = new DatagramSocket(8888);
//创建一个字节数组当做接收信息的容器
byte [] buf = new byte[1024];
//新建一个数据包类对象,用来存储数据包信息
DatagramPacket packet = new DatagramPacket(buf,buf.length);
//接收点对象接收数据,并把数据和客户端信息存储在数据包对象里,
ds.receive(packet);
//信息接收成功,开始解析数据包
byte[] data = packet.getData();
//获取接收的数据包长度(就是数组的被覆盖长度)
int len = packet.getLength();
//把字节转成字符串,并打印
String str = new String(data,0,len);
System.out.println(str);
//返回信息
byte[] byy = "服务器:收到您的来信,感谢访问".getBytes();
//利用接收的数据包,获取客户端的ip和端口,并返回信息
DatagramPacket packet1 = new DatagramPacket(byy,0,byy.length,packet.getAddress(),packet.getPort());
//发送返回信息
ds.send(packet1);
//关闭接收点对象。
ds.close();
}
}
运行结果,目标主机接收到本机程序发送的字符串数据,本机收到目标主机程序返回的字符串信息。
1.
//TCP传输程序
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
InetAddress inetAddress = InetAddress.getLocalHost();
//InetAddress inetAddress = InetAddress.getByAddress(new byte[]{10,10,92,(byte) 162});
Socket socket = new Socket(inetAddress,9999);
OutputStream ops = socket.getOutputStream();
FileInputStream fips = new FileInputStream("C:\\Users\\Administrator\\Desktop\\09.zip");
byte[] bytes = new byte[2048*5];
int len;
while ((len = fips.read(bytes))!=-1) {
ops.write(bytes,0,len);
}
fips.close();
ops.close();
socket.close();
}
}
//tcp接收程序
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket s = new ServerSocket(9999);
Socket accept = s.accept();
InputStream inputStream = accept.getInputStream();
FileOutputStream f = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\2.zip");
byte[] b = new byte[2048*5];
int len;
while ((len = inputStream.read(b))!=-1) {
f.write(b,0,len);
}
f.close();
s.close();
}
}
2.
//发送端
import java.io.FileInputStream;
import java.net.*;
public class one {
public static void main(String[] args) throws Exception {
int i=0 ;
InetAddress ip = InetAddress.getLocalHost();
DatagramSocket ds = new DatagramSocket(5555);
FileInputStream fips = new FileInputStream("C:\\Users\\Administrator\\Desktop\\09.zip");
int sign= 0;
while (true) {
byte[] b = new byte[1024*50];
i=fips.read(b);
DatagramPacket data = new DatagramPacket(b,0,i,ip,9999);
ds.send(data);
sign++;
Thread.sleep(2);
if (i<1024*50) {
break;
}
}
System.out.print(i+" ");
System.out.println(sign);
}
}
//接收端
import java.io.FileOutputStream;
import java.net.*;
public class two {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket(9999);
FileOutputStream f = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\9.zip");
//InetSocketAddress ip = new InetSocketAddress(InetAddress.getLocalHost(),9999);
int sign=0;
while (true) {
byte[] arr = new byte[1024*50];
DatagramPacket pa = new DatagramPacket(arr,arr.length);
ds.receive(pa);
byte[] re = pa.getData();
int len = pa.getLength();
f.write(re,0,len);
sign++;
if (len<1024*50) {
break;
}
}
System.out.println(sign);
}
}