Java网络编程

it2024-01-01  62

文章目录

1.InetAddress2. Socket3. 面向TCP网络编程3.1 示例1: 客户端向服务端发送一个字符串,服务端将字符串显示在命令行中3.2 示例2: 客户端发送一个文件,服务端接收文件并存到本地,并且服务器端给予一个反馈 4. 面向UDP网络编程5. URL编程

1.InetAddress


进行网络通信必不可少的就是ip,在java中,万物皆对象,所以java使用InetAddress类来代表ip地址。用一个具体的InetAddress对象来代表一个ip.

inetAddress 没有构造器, 一般通过静态方法:getByName 来获取它的一个实例。

通过构造器来创建类的实例是java中创建对象最常用的方法,还可以通过:反射 ;调用对象的clone;反序列化;来创建对象,这里inetAddress一个是通过clone来创建对象的。

InetAddress.getByName 不只可以传入ip地址,也可以传入一个域名,java会将这个域名发送到DNS中去解析,最后返回这个域名的ip。如果在DNS解析的过程中,电脑断网了将会报错

public static void inetTest() throws IOException { InetAddress inet = InetAddress.getByName("www.bilibili.com"); //将域名作为参数传入 InetAddress inet1 = InetAddress.getLocalHost();//直接获取本机 InetAddress inet2 = InetAddress.getByName("127.0.0.1"); // 将ip地址作为参数传入 //直接打印对象,也就是调用了toString方法 System.out.println(inet); //getAddress():返回一个byte型数组,里面存储了ip地址,以'.'为分隔符 System.out.println(Arrays.toString(inet.getAddress())); //getHostAddress():返回该实例对应的ip地址 System.out.println(inet.getHostAddress()); //getHostName():返回该实例的ip地址对应的主机名(域名) System.out.println(inet.getHostName()); //System.out.println(inet.getCanonicalHostName()); System.out.println(inet.isReachable(1000)); }

2. Socket


ip+端口号 就是一个网络套接字:socket。java将ip+端口号封装成一个socket,Socket是基于应用服务与TCP/IP通信之间的一个抽象,他将TCP/IP协议里面复杂的通信逻辑进行分装,对用户来说,只要通过一组简单的API就可以实现网络的连接

3. 面向TCP网络编程


3.1 示例1: 客户端向服务端发送一个字符串,服务端将字符串显示在命令行中

客户端:

public static void client() { Socket socket = null; OutputStream outputStream = null; try { InetAddress inet = InetAddress.getByName("127.0.0.1"); socket = new Socket(inet, 9090); outputStream = socket.getOutputStream(); outputStream.write("hello!".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }

服务端

public static void server() { ServerSocket serverSocket = null; Socket socket = null; InputStream is = null; ByteArrayOutputStream baos = null; try { serverSocket = new ServerSocket(9090); //接收来自客户端的socekt socket = serverSocket.accept(); //获取一个针对socket的一个流 is = socket.getInputStream(); //ByteArrayOutputStream 它也是节点流,与之前的不一样,它是用来访问数组的,而不是访文件的,所以它不需要传入File类 //还有类似的访问管道的流,访问字符串的流它们都是节点流 //因为在这里我们只需要在控制台输出就可以,不需要持久化到文件中,所以我们就选择访问数组的输出流 baos = new ByteArrayOutputStream(); int len; byte[] buffer = new byte[20]; while ((len = is.read(buffer)) != -1) { baos.write(buffer, 0, len); } //这个写法不好,会出现乱码 // byte[] buffer = new byte[20]; // int len; // while((len = is.read(buffer)) != -1){ // 此处强制将buffer中的数据转化成string,可能会出现乱码 // String str = new String(buffer,0,len); // System.out.println(str); // } System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); } finally { if (baos != null) { try { baos.close(); } catch (IOException e) { e.printStackTrace(); } } if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }

3.2 示例2: 客户端发送一个文件,服务端接收文件并存到本地,并且服务器端给予一个反馈


客户端:

//客户端发送一个文件,服务端接收文件并存到本地 public static void client2() throws IOException { //创建一个输入流,准备使用该流读取图片二进制数据至内存,使用buffered速度更快 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("test.png"))); //获取一个socket Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000); // 获取针对该socket的输出流,准备使用该流将图片中的数据写出内存,再通过socket送至服务端 OutputStream os = socket.getOutputStream(); //创建一个字节数组,在内存中充当中转站 byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1){//使用bis将数据读入,存到字节数组中 os.write(buffer,0,len);//使用os将字节数组中的数据写出,并通过socket传送至服务端 } //我们知道 在文件读到文件末尾就会返回-1,循环结束,但是在socket中,不知道什么时候返回-1 //所以,我们要在发送数据的一方,在发送完数据之后 shutdown 这个socket对应的输出流 //目的就是告诉接收方,数据传送完成,让他结束read方法。 socket.shutdownOutput(); //接收服务端的反馈 InputStream is = socket.getInputStream();//获取一个对socket的输入流 ByteArrayOutputStream baos = new ByteArrayOutputStream();// 用来将数据输出到控制台 byte[] buffer2 = new byte[20]; int len2; while((len2 = is.read(buffer2)) != -1){ baos.write(buffer2,0,len2); } System.out.println(baos.toString()); //关闭资源 is.close(); baos.close(); bis.close(); os.close(); socket.close(); }

服务端:

//客户端发送一个文件,服务端接收文件并存到本地 public static void server2() throws IOException { //创建一个输出流,作用是将socket接收到的数据,从内存中写出到文件 BufferedOutputStream bus = new BufferedOutputStream(new FileOutputStream(new File("transfered.png"))); //创建一个ServerSocket,服务端的socket和客户端的socket肯定会不一样,它不需要指明ip,因为它就是服务端,它要监听端口等 ServerSocket ss = new ServerSocket(9000); //接收客户端的socket Socket socket = ss.accept(); //获取一个作用于socket的输入流, 并用缓冲流包一下,更快 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] buffer = new byte[10]; int len; while((len = bis.read(buffer)) != -1){//使用bis将数据读入,存到字节数组中 bus.write(buffer,0,len);//使用bus将字节数组中的数据写出到本地文件 } //资源关闭 bus.close(); bis.close(); socket.close(); ss.close(); }

4. 面向UDP网络编程

类DatagramSocket 和 DatagramPacket 实现了基于UDP 协议网络程序。

UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。

DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。

UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。

接收端

public static void main(String[] args) throws IOException { receiver(); } public static void receiver() throws IOException { DatagramSocket socket = new DatagramSocket(9000); byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length); socket.receive(packet); //数据存在buffer中,可以直接来操作这个数组,也可以来操作数据包 System.out.println(new String(buffer,0,buffer.length)); System.out.println(new String(packet.getData(),0,packet.getLength())); socket.close(); }

发送端

public static void main(String[] args) throws IOException { sender(); } public static void sender() throws IOException { //UDP直接在每一个数据包中嵌入信息,面向非连接,所以不需要在socket中指明接收端的ip DatagramSocket socket = new DatagramSocket(); //封装一个数据报 String str = "a data"; byte[] data = str.getBytes(); InetAddress inet = InetAddress.getByName("127.0.0.1"); DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9000); socket.send(packet); socket.close(); }

5. URL编程


这就和爬虫一样了

public class URLTest { public static void test1() { HttpsURLConnection connection = null; InputStream is = null; FileOutputStream fos = null; try { URL url = new URL("https://www.baidu.com"); connection = (HttpsURLConnection) url.openConnection(); connection.connect(); is = connection.getInputStream(); fos = new FileOutputStream("baidu.html"); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null){ connection.disconnect(); } } } public static void main(String[] args) throws IOException { test1(); } }
最新回复(0)