本文主要讲述java的网络知识,以及网络编程所需要使用的类。
一. InetAdress类
InetAddress类,用于获取主机名和IP地址【域名】
public class InetAddressTest { public static void main(String[] args) throws UnknownHostException { // 1.获取本机的Inet4Address对象 InetAddress localHost = Inet4Address.getLocalHost(); System.out.println("本地主机的InetAddress对象: " + localHost); // 2.根据主机的名称,获取Inet4Address对象 InetAddress host1 = Inet4Address.getByName("DESKTOP-TIT5KO3"); System.out.println("本地主机的InetAddress对象: " + host1); // 3.根据域名,获取InetAddress对象 InetAddress host2 = Inet4Address.getByName("www.baidu.com"); System.out.println("百度的InetAddress对象: " + host2); // 4.根据InetAddress对象,获取IP地址 String hostAddress = host2.getHostAddress(); System.out.println("IP地址: " + hostAddress); // 5.根据InetAddress对象,获取主机名\域名 String hostName = host2.getHostName(); System.out.println("域名: " + hostName); } }
二. Socket类
案例一:使用字节流,编写服务端和客户端,要求服务端接受客户端发过来的数据,并显示在控制台上
服务端:
public class SocketTCPServer { public static void main(String[] args) throws Exception{ // 1. 服务端,创建ServerSocket对象,在本主机监听9999端口,等待客户端的链接 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端的serverSocket正在监听9999端口,等待连接"); // 2. 客户端如果链接了9999端口,返回socket对象;否则,程序阻塞,无法向下执行 // serverSocket.accept()会返回多个Socket【多个客户端并发】 Socket socket = serverSocket.accept(); System.out.println("服务器端返回的serverSocket: " + socket.getClass()); // 3. 客户端socket对象写入数据,服务端socket对象获取输入流 getOutputStream,读入数据 InputStream inputStream = socket.getInputStream(); // 4. 使用inputStream读取数据 byte[] bytes = new byte[1024]; // 读取数据所需要的字节数组 int readLen = 0; // 读取数据的长度 // 读取长度是-1,则表示数据已经读完 while((readLen = inputStream.read(bytes)) != -1){ // 每次按照bytes数组长度,读取数据内容,读取完毕,返回-1. // new String(bytes,0,readLen),防止不足bytes数组长度的数据无法显示 System.out.print(new String(bytes,0,readLen)); } System.out.println("服务器端读取数据完毕"); // 5. 关闭输入流和socket【服务端】 inputStream.close(); socket.close(); serverSocket.close(); } }
客户端:
public class SocketTCPClient01 { public static void main(String[] args) throws Exception{ // 1. 客户端,创建socket对象 new Socket(ip地址,端口号) // ip地址,是服务端所在主机的ip地址,端口号是服务端监听的端口号 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端返回的serverSocket: " + socket.getClass()); // 2. 通过socket对象,获取socket的输出流getOutputStream(),写入数据 OutputStream outputStream = socket.getOutputStream(); // 3. 使用OutputStream写入数据 outputStream.write("hello,I am client01\n".getBytes()); // 4. 关闭输出流和socket【客户端】 outputStream.close(); socket.close(); // System.out.println("客户端退出"); } }
案例二:使用字节流,编写服务端和客户端,要求服务端接收客户端的消息A,发送消息B;客户端发送消息A,接收服务端的消息B
错误写法:
服务端:
public class SocketServer { public static void main(String[] args) throws Exception{ // 1. 创建socketServer对象,端口号9999 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("启动服务器..."); // 2. 监听客户端 Socket socket = serverSocket.accept(); // 3. 获取输入流 InputStream inputStream = socket.getInputStream(); int readLen = 0; byte[] bytes = new byte[1024]; while((readLen = inputStream.read(bytes)) != -1){ String s = new String(bytes, 0, readLen); System.out.println(s); } // 4. 获取输出流 OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello Client".getBytes());// 5. 关闭输入输出流 outputStream.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
客户端:
public class SocketClient01 { public static void main(String[] args) throws IOException { // 1. 创建socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("启动客户端..."); // 2. 获取OutPut OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello Server".getBytes()); // 3. 获取输入流 InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int readLen = 0; while((readLen = inputStream.read(bytes)) != -1){ String s = new String(bytes, 0, readLen); System.out.println(s); } // 4. 关闭输入输出流 outputStream.close(); inputStream.close(); socket.close(); } }
此时,启动服务端,监听客户端是否链接,启动客户端,在客户端写入hello Server,服务端读取到了数据,并将其显示,但是服务端并不知道客户端在什么时候写入结束,因此服务端会在数据连接中一直进行读操作,客户端在等待接收服务端写入的数据,随即发生了服务端和客户端都阻塞的现象。
正确写法:
// 设置输出的结束标记 socket.shutdownOutput(); // 设置输入的结束标记 socket.shutdownInput();
当写入或者读取结束时,要设置写入或者读取结束的标记
服务端:
public class SocketServer { public static void main(String[] args) throws Exception{ // 1. 创建socketServer对象,端口号9999 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("启动服务器..."); // 2. 监听客户端 Socket socket = serverSocket.accept(); // 3. 获取输入流 InputStream inputStream = socket.getInputStream(); int readLen = 0; byte[] bytes = new byte[1024]; while((readLen = inputStream.read(bytes)) != -1){ String s = new String(bytes, 0, readLen); System.out.println(s); } // 设置输入结束的标记 socket.shutdownInput(); // 4. 获取输出流 OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello Client".getBytes()); // 设置输出的结束标记 socket.shutdownOutput(); // 5. 关闭输入输出流 outputStream.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
客户端:
public class SocketClient01 { public static void main(String[] args) throws IOException { // 1. 创建socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("启动客户端..."); // 2. 获取OutPut OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello Server\n".getBytes()); // 设置输出的结束标记 socket.shutdownOutput(); // 3. 获取输入流 InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int readLen = 0; while((readLen = inputStream.read(bytes)) != -1){ String s = new String(bytes, 0, readLen); System.out.println(s); } // 设置输入的结束标记 socket.shutdownInput(); // 4. 关闭输入输出流 outputStream.close(); inputStream.close(); socket.close(); } }
运行结果:
案例三:使用字符流,编写服务端和客户端,要求服务端接收客户端的消息A,发送消息B;客户端发送消息A,接收服务端的消息B。
通过socket只能获得字节流,因此需要转换流,将原本的字节流转换成字符流。
服务端:
@SuppressWarnings({"all"}) public class SocketTCPServer { public static void main(String[] args) throws Exception{ ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务器开始启动..."); Socket socket = serverSocket.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String str = null; while((str = br.readLine()) != null){ System.out.println(str); } socket.shutdownInput(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"utf-8")); bw.write("hello client\n"); bw.write("I am server"); bw.flush(); socket.shutdownOutput(); br.close(); bw.close(); socket.close(); serverSocket.close(); } }
客户端:
@SuppressWarnings({"all"}) public class SocketTCPClient { public static void main(String[] args) throws Exception{ Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端开始启动..."); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8")); bw.write("hello server\n"); bw.write("I am client"); bw.flush(); socket.shutdownOutput(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String str = null; while((str = br.readLine()) != null){ System.out.println(str); } socket.shutdownInput(); bw.close(); br.close(); socket.close(); } }
注意:在写入数据后,使用处理流bw.flush(),手动刷新,将写入的数据放入数据通道。
运行结果:
案例四:使用字节流,客户端向服务端传输图片,传送完成,服务端在src下保存图片,并且向客户端发送“收到图片”
注意:写入数据通道内容后,手动刷新以及添加写入和读取的结束标志。
服务端:
@SuppressWarnings({"all"}) public class SocketServer01 { public static void main(String[] args) throws Exception{ ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务器监听"); Socket socket = serverSocket.accept(); // 1.获取socket对象的输入流 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); // 2.获取输出流,写入数据 String filePath = "src\\111.jpg"; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); int readLen = 0; byte[] bytes = new byte[1024]; while((readLen = bis.read(bytes)) != -1){ bos.write(bytes,0,readLen); } socket.shutdownInput(); BufferedOutputStream boss = new BufferedOutputStream(socket.getOutputStream()); boss.write("收到图片".getBytes()); boss.flush(); socket.shutdownOutput(); bis.close(); bos.close(); boss.close(); socket.close(); serverSocket.close(); } }
客户端:
@SuppressWarnings({"all"}) public class SocketClient01 { public static void main(String[] args) throws Exception{ Socket socket = new Socket(InetAddress.getLocalHost(), 9999); System.out.println("客户端开始启动"); // 1.获取socket的输出流->处理流 OutputStream os = socket.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(os); // 2.获取socket的输入流->处理流 String filePath = "F:\\desk.jpg"; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); int readLen = 0; byte[] bytes = new byte[1024]; while((readLen = bis.read(bytes)) != -1){ bos.write(bytes,0,readLen); } // 循环写入的话,需要将输出流不断地刷新,否则数据传输不完整 bos.flush(); socket.shutdownOutput(); BufferedInputStream biss = new BufferedInputStream(socket.getInputStream()); while((readLen = biss.read(bytes)) != -1){ System.out.println(new String(bytes,0,readLen)); } bos.close(); bis.close(); biss.close(); socket.close(); } }
运行结果:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/98953.html