Java中的三种通信(TCP、UDP、URL)实例
(1)基于Socket的Tcp通信
1)客户端Socket的包含以下四个基本的步骤:
创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输。
按照协议对 Socket进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
关闭 Socket:断开客户端到服务器的连接,释放线路
2)服务器端程序包含以下四个基本的步骤:
调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。监听客户端的请求。
调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
调用该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出流和输入流,开始网络数据的发送和接收。
关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。
TCP实例:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import org.junit.Test;
//TCP实例:从客户端(Client)发送文件(实例中以照片为例)给服务端(Server),服务端保存到本地。并返回“发送成功”给客户端。并关闭相应的连接。
public class testTcp3 {
//客户端
@Test
public void client(){
//1.创建Socket对象,输出流对象(输出给服务端),文件输入流对象(读取文件到客户端)
Socket socket = null;
OutputStream os = null;
FileInputStream fis = null;
//2.接收来自于服务端的信息
InputStream is = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"),8989);//通过InetAddress的getByName()方法获取要链接的地址和端口号
os = socket.getOutputStream();
fis = new FileInputStream(new File("崔洪振367.png"));
//3、将文件(照片)写入到客户端的字节数组中
byte[] b = new byte[1024];
int len;
while((len = fis.read(b)) != -1){
os.write(b, 0, len);
}
//4.要关闭socket的发送,便于服务端接收
socket.shutdownOutput();
//5、输入流,用于接收服务端发送的数据,并通过写入到字节,打印到控制台
is = socket.getInputStream();
byte[] b1 = new byte[1024];
int length;
while((length = is.read(b1)) != -1){
String str = new String(b1, 0, length);
System.out.print(str);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//6、按照顺序(先开后关)关闭所有对象和socket,要使用try-catch来处理异常
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
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(){
//1创建一个ServerSocket的对象
ServerSocket so = null;
//2调用其accept()方法,返回一个Socket的对象
Socket s = null;
//3、将从客户端发来的消息保存到本地
InputStream is = null;
FileOutputStream fos = null;
//4、用来回复客户端的语句的对象
OutputStream os = null;
try {
so = new ServerSocket(8989);
s = so.accept();
is = s.getInputStream();
fos = new FileOutputStream(new File("1.png"));
//5、写入到字节数组中
byte[] b = new byte[1024];
int len;
while((len = is.read(b)) != -1){
fos.write(b, 0, len);
}
//打印客户端的地址
System.out.println("收到来自:" + s.getInetAddress().getHostAddress() + "的文件!");
//6、将字节数组中的照片保存到本地
os = s.getOutputStream();
os.write("我已经收到你发送的照片!".getBytes());
}catch (Exception e) {
e.printStackTrace();
}finally{
//6、按照顺序(先开后关)关闭所有对象和ServerSocket的对象,要使用try-catch来处理异常
if(os != null){
try {
so.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(s != null){
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(so != null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(2)UDP网络通信
的通信过程分为发送端和接收端。发送端与接收端是两个独立的运行程序,其中两端使用的类是一致的步骤也具有一致性,其中涉及的类为:DatagramSocket与DatagramPacket。其实现步骤为:
)建立发送端,接收端
)建立数据包
)调用Socket的发送、接收方法
)关闭Socket
UDP实例:
package TestTCP1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import org.junit.Test;
//UDP编程的实现:类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
//UDP数据报通过数据报套接字DatagramSocket发送和接收,DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
//UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。
//(缺点是;)通信过程中系统不能保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
public class testUDP {
//发送端
@Test
public void send(){
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
byte[] b = "我是发送端".getBytes();
//创建一个数据报:每一个数据报不大于64k,且都记录着数据信息:发送端的IP、端口号,要发送到的接收端的IP、端口号。
DatagramPacket pack = new DatagramPacket(b, 0, b.length,
InetAddress.getByName("127.0.0.1"), 9090);
ds.send(pack);//通过send()方法将数据报发送给接收端
}catch (IOException e) {
e.printStackTrace();
}finally{
//关闭DatagramSocket的对象
if(ds != null){
ds.close();
}
}
}
@Test
public void receive(){
DatagramSocket ds = null;
try {
ds = new DatagramSocket(9090);//需要设置端口号
byte[] b = new byte[1024];//将发送端发送的信息写入到字节数组中
DatagramPacket pack = new DatagramPacket(b, 0, b.length);//将字节数组中的信息存入到数据报中
ds.receive(pack);//接收端用receive()方法接收数据报
String str = new String(pack.getData(), 0, b.length);//数据报转为字符串,注意参数是pack.getData()
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭DatagramSocket的对象
if(ds != null){
ds.close();
}
}
}
}
(3)URL通信编程
编程用的主要类是URL类,其过程和相关方法在注释中以给出。
URL实例:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
/**
* URL:统一资源定位符
* URL的组成结构:<传输协议>://<主机名>:<端口号>/<文件名>
* URL中常用的方法:
public String getProtocol( ) 获取该URL的协议名
public String getHost( ) 获取该URL的主机名
public String getPort( ) 获取该URL的端口号
public String getPath( ) 获取该URL的文件路径
public String getFile( ) 获取该URL的文件名
public String getRef( ) 获取该URL在文件中的相对位置
public String getQuery( ) 获取该URL的查询名
* */
//实例:通过URL将网页内容读取到控制台。这里只考虑通信问题,编码等问题忽略。
public class testURL {
public static void main(String[] args) {
InputStream is1 = null;
FileOutputStream fos = null;
try {
//1.创建一个URL的对象
URL url = new URL("https://www.baidu.com/");//""中是URL的地址
//将服务端的资源读取进来:openStream()
InputStream is = url.openStream();
byte[] b = new byte[1024];
int len;
while((len = is.read(b)) != -1){
String str = new String(b,0,len);
System.out.println(str);
}
is.close();
//如果既有数据的输入,又有数据的输出,则考虑使用URLConnection
URLConnection urlConn = url.openConnection();
is1 = urlConn.getInputStream();
fos = new FileOutputStream(new File("abc.txt"));
byte[] b1 = new byte[20];
int len1;
while((len1 = is1.read(b1)) != -1){
fos.write(b1, 0, len1);
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//关闭对应的输入输出流
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is1 != null){
try {
is1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}