韩顺平Java39——网络编程
网络相关概念
客户端链接的时候构造器记得写IP+端口号
- 网络通信:
- 网络:
- IP地址:
IPv6的地址长度为128位,是IPv4地址长度的4倍。于是IPv4点分十进制格式不再适用,采用十六进制表示。IPv6有3种表示方法。
win查看命令:ipconfig
- 域名和端口号:
- 网络通信协议
协议可以简单理解为数据的组织形式
- TCP和UDP
三次握手(bushi)
InetAddress类
package com.recorder.api; import java.net.InetAddress; import java.net.UnknownHostException; /** * @author 紫英 * @version 1.0 * @discription */ public class Api_ { public static void main(String[] args) throws UnknownHostException { //1.获取本机的InetAddress对象 InetAddress localHost = InetAddress.getLocalHost(); System.out.println("本机的InetAddress对象: " + localHost);////2.根据指定主机名获取InetAddress对象 InetAddress localHost2 = InetAddress.getByName("MrMRecorder"); System.out.println("根据指定主机名获取InetAddress对象: " + localHost2); //3.根据域名获取InetAddress对象 InetAddress baidu = InetAddress.getByName("www.baidu.com"); System.out.println("根据域名www.baidu.com获取InetAddress对象: " + baidu); //4.通过InetAddress对象获取对应的地址 String baiduAddress = baidu.getHostAddress(); System.out.println("通过InetAddress对象获取对应的地址: " + baiduAddress); //5.通过InetAddress对象获取对应的主机名或域名 String baiduName = baidu.getHostName(); System.out.println("通过InetAddress对象获取对应的主机名或域名: " + baiduName); } }
Socket
TCP网络通信编程
-
练习1:
思路分析:
- 代码演示
服务器端:
package com.recorder.api.socket; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /** * @author 紫英 * @version 1.0 * @discription 服务端 */ public class Tcp01Server { public static void main(String[] args) throws IOException { // 1.在本机的9999端口监听,等待连接 // 注意:要求本机没有其他服务正在监听9999 // 注意:这个serverSocket可以通过serverSocket.accept()返回多个Socket, // 即多个客户端链接服务器的并发 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务器端在9999端口监听,等待连接..."); // 2.当没有客户端连接9999端口时程序会阻塞,等待连接 // 如果有程序连接则会返回socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("socket类型:" + socket.getClass()); // 3.通过 socket.getInputStream()读取客户端写入到数据通道的数据并显示 // socket.getInputStream() InputStream inputStream = socket.getInputStream(); // 4.IO读取 byte[] bytes = new byte[1024]; int readLen = 0; while ((readLen = inputStream.read(bytes)) != -1){ System.out.println(new String(bytes,0,readLen)); //根据读取到的实际长度显示对应内容 } // 4.关闭对应的流和socket对象 inputStream.close(); socket.close(); serverSocket.close(); System.out.println("服务器端已退出!"); } }
客户端:
package com.recorder.api.socket; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * @author 紫英 * @version 1.0 * @discription 客户端 */ public class Tcp01Client { public static void main(String[] args) throws IOException { // 1.链接服务器端(ip,端口) // 连接本机的服务器端,如果连接成功返回socket对象 // (因为是演示连接本机,如果连接别的服务器则输入对应的ip地址) Socket socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端socket返回:" + socket.getClass()); // 2.连接成功后生成socket对象,通过 socket.getOutputStream() // 得到和socket对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); // 3.通过输出流写入数据到数据通道 outputStream.write("hello,server!".getBytes()); // 4.关闭对应的流和socket对象 outputStream.close(); socket.close(); System.out.println("客户端已退出!"); } }
-
练习2:
思路分析:
服务器端:
package com.recorder.api.socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /** * @author 紫英 * @version 1.0 * @discription 服务端 */ public class Tcp02Server { public static void main(String[] args) throws IOException { // 1.在本机的9999端口监听,等待连接 // 注意:要求本机没有其他服务正在监听9999 // 注意:这个serverSocket可以通过serverSocket.accept()返回多个Socket, // 即多个客户端链接服务器的并发 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务器端在9999端口监听,等待连接..."); // 2.当没有客户端连接9999端口时程序会阻塞,等待连接 // 如果有程序连接则会返回socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("socket类型:" + socket.getClass()); // 3.通过 socket.getInputStream()读取客户端写入到数据通道的数据并显示 // socket.getInputStream() InputStream inputStream = socket.getInputStream(); // 4.IO读取 byte[] bytes = new byte[1024]; int readLen = 0; while ((readLen = inputStream.read(bytes)) != -1) { System.out.println("客户端发来消息: " + new String(bytes, 0, readLen)); //根据读取到的实际长度显示对应内容 } // 5.向客户端发送消息 OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello,client!".getBytes()); socket.shutdownOutput();//设置结束标记 // 6.关闭对应的流和socket对象 outputStream.close(); inputStream.close(); socket.close(); serverSocket.close(); System.out.println("服务器端已退出!"); } }
客户端:
package com.recorder.api.socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; /** * @author 紫英 * @version 1.0 * @discription 客户端 */ public class Tcp02Client { public static void main(String[] args) throws IOException { // 1.链接服务器端(ip,端口) // 连接本机的服务器端,如果连接成功返回socket对象 // (因为是演示连接本机,如果连接别的服务器则输入对应的ip地址) Socket socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端socket返回:" + socket.getClass()); // 2.连接成功后生成socket对象,通过 socket.getOutputStream() // 得到和socket对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); // 3.通过输出流写入数据到数据通道 outputStream.write("hello,server!".getBytes()); socket.shutdownOutput(); 设置结束标记 // 4.接收服务器端的数据 InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int readLen = 0; while ((readLen = inputStream.read(bytes)) != -1) { System.out.println("服务器端发来消息: " + new String(bytes, 0, readLen)); //根据读取到的实际长度显示对应内容 } // 5.关闭对应的流和socket对象 inputStream.close(); outputStream.close(); socket.close(); System.out.println("客户端已退出!"); } }
练习3:
思路分析:
服务器端:
package com.recorder.api.socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * @author 紫英 * @version 1.0 * @discription 服务端(字符流) */ @SuppressWarnings("all") public class Tcp03Server { public static void main(String[] args) throws IOException { // 1.在本机的9999端口监听,等待连接 // 注意:要求本机没有其他服务正在监听9999 // 注意:这个serverSocket可以通过serverSocket.accept()返回多个Socket, // 即多个客户端链接服务器的并发 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务器端在9999端口监听,等待连接..."); // 2.当没有客户端连接9999端口时程序会阻塞,等待连接 // 如果有程序连接则会返回socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("socket类型:" + socket.getClass()); // 3.读取客户端写入到数据通道的数据并显示 InputStream inputStream = socket.getInputStream(); // 4.IO读取(字符流) BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println("客户端发来消息: " + s); //根据读取到的实际长度显示对应内容 // 5.向客户端发送消息 OutputStream outputStream = socket.getOutputStream(); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,client!(字符流)"); bufferedWriter.flush(); bufferedWriter.newLine();//设置结束标记 // 6.关闭对应的流和socket对象 bufferedWriter.close(); bufferedReader.close(); outputStream.close(); inputStream.close(); socket.close(); serverSocket.close(); System.out.println("服务器端已退出!"); } }
客户端:
package com.recorder.api.socket; import java.io.*; import java.net.InetAddress; import java.net.Socket; /** * @author 紫英 * @version 1.0 * @discription 客户端 (字符流) */ @SuppressWarnings("all") public class Tcp03Client { public static void main(String[] args) throws IOException { // 1.链接服务器端(ip,端口) // 连接本机的服务器端,如果连接成功返回socket对象 // (因为是演示连接本机,如果连接别的服务器则输入对应的ip地址) Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端socket返回:" + socket.getClass()); // 2.连接成功后生成socket对象,通过 socket.getOutputStream() // 得到和socket对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); // 3.通过输出流写入数据到数据通道 BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,server!(字符流)"); bufferedWriter.newLine();//换行符——表示输入结束(要求对方使用readline!!!!) bufferedWriter.flush();//需要手动刷新 // 4.接收服务器端的数据 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println("服务器端发来消息: " + s); // 5.关闭对应的流和socket对象 bufferedReader.close(); bufferedReader.close(); inputStream.close(); outputStream.close(); socket.close(); System.out.println("客户端已退出!"); } }
练习4:
思路分析:
服务器端:
package com.recorder.api.upload; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * @author 紫英 * @version 1.0 * @discription 文件上传服务器端 */ public class TcpFileUploadServer { public static void main(String[] args) throws Exception { String filePath = "src\\pic.jpg"; // 1.服务器端在本机监听8888端口 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("监听8888端口等待客户端连接..."); // 2.等待连接 Socket socket = serverSocket.accept(); // 3.创建输入流读取客户端发来的数据 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] bytes = SteamUtil.streamToByteArray(bis); // 4.将得到的字节数组写入到指定文件路径,得到文件 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes); bos.close(); // 5.向客户端发送:收到图片 //socket获取输出流 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("收到图片!"); writer.flush();//把内容刷新到数据通道 socket.shutdownOutput();//设置结束标记 //关闭其他流 writer.close(); bis.close(); socket.close(); serverSocket.close(); System.out.println("服务器端关闭!"); } }
客户端:
package com.recorder.api.upload; import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; /** * @author 紫英 * @version 1.0 * @discription 文件上传客户端 */ public class TcpFileUploadClient { public static void main(String[] args) throws Exception { // 1.客户端连接服务器端8888端口,得到socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 8888); // 2.创建读取图片文件的输入流 String filePath = "e:\\wu.jpg"; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); byte[] bytes = SteamUtil.streamToByteArray(bis); //这里的字节数组存放的就是对应的文件内容 // 3.通过socket获取输出流将数据(字节数组)发送给服务器端 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); //将文件对应的字节数组内容写入到数据通道 bos.write(bytes); //设置结束标记 socket.shutdownOutput(); bis.close(); // 4.接收服务器端发送的消息 InputStream inputStream = socket.getInputStream(); //使用工具类将InputStream转化为String String s = SteamUtil.streamToString(inputStream); System.out.println("服务器端发来消息:" + s); //关闭对应的流 socket.close(); bos.close(); inputStream.close(); System.out.println("客户端关闭!"); } }
工具类:
package com.recorder.api.upload; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.InputStreamReader; /** * @author 紫英 * @version 1.0 * @discription 将输入流转换为byte[] */ public class SteamUtil { public static byte[] streamToByteArray(InputStream is) throws Exception{ ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象 byte []b = new byte[1024]; //字节数组——读取输入流 int len; while ((len = is.read(b))!= -1){ bos.write(b,0,len); //把读取到的数据写入到字节数组流 } byte[] array = bos.toByteArray(); //将bos转为字节数组 bos.close(); return array; } public static String streamToString(InputStream is) throws Exception{ //将输入流数据转换为String BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuffer buffer = new StringBuffer(); String line = null; while ((line = reader.readLine())!=null){ buffer.append(line + "\r\n"); } return buffer.toString(); } }
netstat命令
这里127.0.0.1 和 0.0.0.0都表示本机
外部地址表示有没有外部的链接连接到本机,显示的是连接到本机的外部链接的ip地址和端口号
状态:LISTRNING表示正在监听 ESTABLING表示已连接
-anb参数可以查看是哪个程序正在监听(需要管理员身份)
- 冷知识
UDP网络通信编程(了解)
- 练习1:
receiver端:
package com.recorder.api.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; /** * @author 紫英 * @version 1.0 * @discription 接收端 */ public class UdpReceiver { public static void main(String[] args) throws IOException { //1.创建一个DatagramSocket对象,在9999端口等待接收数据 DatagramSocket datagramSocket = new DatagramSocket(9999); // 2.创建一个DatagramPacket对象接收数据(一个数据包最大64KB) byte[] bytes = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length); // 3.调用接收方法,将通过网络传输的DatagramPacket对象填充到datagramSocket中 System.out.println("receiver等待接收数据..."); // 当没有数据发送到9999本机的端口时就会阻塞等待 datagramSocket.receive(datagramPacket); // 4.对datagramPacket进行拆包取出数据并展示 int len = datagramPacket.getLength(); byte[] b = datagramPacket.getData(); String s = new String(b,0,len); System.out.println("sender发来消息:" + s); // 5.向sender端发送消息 byte[] data = "下次一定!".getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.47.1"), 9998); datagramSocket.send(packet); // 关闭资源 datagramSocket.close(); System.out.println("receiver端退出"); } }
sender端:
package com.recorder.api.udp; import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; /** * @author 紫英 * @version 1.0 * @discription 发送端 */ public class UdpSender { public static void main(String[] args) throws IOException { //1.创建一个DatagramSocket对象,在9998端口等待接收数据 DatagramSocket datagramSocket = new DatagramSocket(9998); // 2.将需要发送的数据封装到DatagramPacket对象 byte[] data = "hello 明天出来玩!".getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.47.1"), 9999); datagramSocket.send(packet); byte[] bytes = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length); // 3.调用接收方法,将通过网络传输的DatagramPacket对象填充到datagramSocket中 System.out.println("receiver等待接收数据..."); // 当没有数据发送到9999本机的端口时就会阻塞等待 datagramSocket.receive(datagramPacket); // 4.对datagramPacket进行拆包取出数据并展示 int len = datagramPacket.getLength(); byte[] b = datagramPacket.getData(); String s = new String(b,0,len); System.out.println("receiver端发来消息:" + s); //关闭资源 datagramSocket.close(); System.out.println("sender端退出"); } }
本文来自博客园,作者:紫英626,转载请注明原文链接:https://www.cnblogs.com/recorderM/p/15858257.html