本文主要讲述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(); } }
运行结果:
标签:java,socket,知识,网络,System,close,out,服务端,客户端 From: https://www.cnblogs.com/zwgitOne123/p/17047093.html