Java语言基础--网络编程

Java语言基础--网络编程

InetAddress

表示主机的地址信息的类

  • 获取本机InetAddress对象getLocalHost
  • 根据指定主机名/域名获取IP地址对象getByName
  • 获取InetAddress对象的主机名getHostName
  • 获取InetAddress对象的地址getHostAddress

Socket

套接字(socket)开发网络应用程序被广泛采用,以至于成为事实上的标准,通信两端都要有Socket作为端点,网络通信就是端点间的通信

socket允许程序把网络连接当作流,数据在两个Socket间通过IO传输;发起通信的程序是客服端,等待通信请求的为服务端

基于客户端-服务端的网络通信,底层使用TCP/IP协议

  • TCP编程
    • 使用Socket对象
    • getOutputStream 写入发送数据
      • shutdownOutput 写入结束标记;
      • 当使用字符流写入时,可以使用write.newLine()设置结束标记,但是要求对方使用readLine()
    • getInputStream 读取接收数据
  • UDP编程
    • 使用DatagramSocket对象和DatagramPacket【数据包/数据报】
    • DatagramSocket指定哪个端口接收数据包
    • DatagramPacket数据对象拆包/装包,数据包最大64K上限

代码案例

  • TCP编程-字节流

    //服务端
    public class SocketTcpServer{
        public static void main(String[] args) throw IPException{
            //监听本机9999端口
            ServerSocket serverSocket = new ServerSocket(9999);
            //阻塞程序等待Socket对象创建,就是链接建立
            Socket socket = serverSocket.accrpt();
            
    		//拿到链接的输入流
            InputStream inputStream = socket.getInputStream();
            //读取=接收数据
            byte[] buf = new byte[1024];
            int readLen = 0;
            while((readLen = inputStream.read())!=-1){
                //直接输出到控制台
                System.out.println(new String(buf,0,readLen));
            }
            
            //拿到链接的输出流
            OutputStream outputStream = socket.getOutputStream();
            //写入=发送数据
            outputStream.write("hello, Client".getBytes());
            //写入结束标记
            socket.shutdownOutput();
            
            //关闭资源
            inputStream.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    //客户端
    public class SocketTCPClient{
        public static void main(String[] args) throws IOException{
            //链接目标主机程序,链接成功会创建Socket对象,这里是本机的9999端口
            Socket socket = new Socket(InetAddress.getLocalHost(),9999);
            
            //拿到链接的输出流
            OutputStream outputStream = socket.getOutputStream();
            //写入=发送数据
            outputStream.write("hello, server".getBytes());
            //写入结束标记
            socket.shutdownOutput();
            
            //拿到链接的输入流
            InputStream inputStream = socket.getInputStream();
            //读取=接收数据
            byte[] buf = new byte[1024];
            int readLen = 0;
            while((readLen = inputStream.read())!=-1){
                //直接输出到控制台
                System.out.println(new String(buf,0,readLen));
            }
            
            //关闭资源
            outputStream.close();
            socket.close();
        }
    }
    
  • TCP编程-字符流

    //服务端
    public class SocketTcpServer{
        public static void main(String[] args) throw IPException{
            //监听本机9999端口
            ServerSocket serverSocket = new ServerSocket(9999);
            //阻塞程序等待Socket对象创建,就是链接建立
            Socket socket = serverSocket.accrpt();
            
    		//拿到链接的输入流
            InputStream inputStream = socket.getInputStream();
            //读取=接收数据
            //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String s = bufferedReader.readLine();
            System.out.println(s);
            
            //拿到链接的输出流
            OutputStream outputStream = socket.getOutputStream();
            //写入=发送数据
            //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write("hello,server 字符流");
            bufferedWriter.newLine();//写入结束标记,此时要求对方使用readLine来接收读取
            bufferedWriter.flush();//使用字符流,需要使用此方法刷新写入,否则不会真正写入对象包含的节点流
            
            //关闭资源
            bufferedReader.close();
            bufferedWriter.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    //客户端
    public class SocketTCPClient{
        public static void main(String[] args) throws IOException{
            //链接目标主机程序,链接成功会创建Socket对象,这里是本机的9999端口
            Socket socket = new Socket(InetAddress.getLocalHost(),9999);
            
            //拿到链接的输出流
            OutputStream outputStream = socket.getOutputStream();
            //写入=发送数据
            //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write("hello,server 字符流");
            bufferedWriter.newLine();//写入结束标记,此时要求对方使用readLine来接收读取
            bufferedWriter.flush();//使用字符流,需要使用此方法刷新写入,否则不会真正写入对象包含的节点流
            
            //拿到链接的输入流
            InputStream inputStream = socket.getInputStream();
            //读取=接收数据
            //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String s = bufferedReader.readLine();
            System.out.println(s);
            
            //关闭资源
            bufferedReader.close();
            bufferedWriter.close();
            socket.close();
        }
    

}


- TCP-文件传输

```java
public class TCPFileUploadServer {
    public static void main(String[] args) throws IOException {
        // 启动服务监听端口
        ServerSocket serverSocket = new ServerSocket(9999);
        // 等待连接
        Socket socket = serverSocket.accept();
        // 接收文件
        InputStream inputStream = socket.getInputStream();
        String filePath = "qie.png";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));

        byte[] bytes = new byte[1024];
        int bytesLen = 0;
        while ((bytesLen=inputStream.read(bytes))!=-1){
            bos.write(bytes,0,bytesLen);
        }

        //关闭资源
        inputStream.close();
        bos.close();
        socket.close();
        serverSocket.close();

    }
public class TCPFileUploadClient {
    public static void main(String[] args) throws IOException {
        //客户端连接服务器
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        //准备发送数据
        String filePath = "e:\\qie.png";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
        OutputStream os = socket.getOutputStream();
        //发送
        byte[] bytes = new byte[1024];
        int bytesLen = 0;
        while ((bytesLen = bis.read(bytes))!=-1){
            os.write(bytes, 0, bytesLen);
        }
        //关闭资源
        os.close();
        bis.close();
        socket.close();
    }
}

工具类中间层

/**
 * 此类用于演示关于流的读写方法
 *
 */
public class StreamUtils {
	/**
	 * 功能:将输入流转换成byte[]
	 * @param is
	 * @return
	 * @throws Exception
	 */
	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.close();
		return array;
	}
	/**
	 * 功能:将InputStream转换成String
	 * @param is
	 * @return
	 * @throws Exception
	 */
	
	public static String streamToString(InputStream is) throws Exception{
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder builder= new StringBuilder();
		String line;
		while((line=reader.readLine())!=null){ //当读取到 null时,就表示结束
			builder.append(line+"\r\n");
		}
		return builder.toString();
		
	}

}
/*
下面是客户端和服务端代码
*/
public class TCPFileUploadServer {
    public static void main(String[] args) throws Exception {

        //1. 服务端在本机监听8888端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务端在8888端口监听....");
        //2. 等待连接
        Socket socket = serverSocket.accept();


        //3. 读取客户端发送的数据
        //   通过Socket得到输入流
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //4. 将得到 bytes 数组,写入到指定的路径,就得到一个文件了
        String destFilePath = "src\\abc.mp4";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bos.write(bytes);
        bos.close();

        // 向客户端回复 "收到图片"
        // 通过socket 获取到输出流(字符)
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        writer.write("收到图片");
        writer.flush();//把内容刷新到数据通道
        socket.shutdownOutput();//设置写入结束标记

        //关闭其他资源
        writer.close();
        bis.close();
        socket.close();
        serverSocket.close();
    }
}

public class TCPFileUploadClient {
    public static void main(String[] args) throws Exception {

        //客户端连接服务端 8888,得到Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
        //创建读取磁盘文件的输入流
        //String filePath = "e:\\qie.png";
        String filePath = "e:\\abc.mp4";
        BufferedInputStream bis  = new BufferedInputStream(new FileInputStream(filePath));

        //bytes 就是filePath对应的字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);

        //通过socket获取到输出流, 将bytes数据发送给服务端
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道
        bis.close();
        socket.shutdownOutput();//设置写入数据的结束标记

        //=====接收从服务端回复的消息=====

        InputStream inputStream = socket.getInputStream();
        //使用StreamUtils 的方法,直接将 inputStream 读取到的内容 转成字符串
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);


        //关闭相关的流
        inputStream.close();
        bos.close();
        socket.close();
    }
}

netstat指令(命令行)

  • 参数-an 查看当前主机网络情况,包括端口监听

  • 参数-an | more 可以分页显示

  • 参数-anb 查看包含程序名的网络情况

    冷知识:客户端连接到服务端,实际上客户端也通过一个端口和服务端进行通讯,这个端口是TCP/IP来随机分配

DatagramSocket

代码案例

public class UDPService {
    public static void main(String[] args) throws IOException {
        //建立入口
        DatagramSocket socket = new DatagramSocket(9999);
        //准备接收数据包
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
        //等待接收数据
        socket.receive(packet);
        //输出数据(拆包)
        String context = new String(packet.getData(), 0, packet.getLength());
        System.out.println(context);

        //准备发送数据包
        byte[] contextByte = "没问题".getBytes();
        DatagramPacket packetSend =
                new DatagramPacket(contextByte,contextByte.length, InetAddress.getByName("192.168.1.18"), 9998);
        //发送数据
        socket.send(packetSend);

        //关闭资源
        socket.close();
    }
}
public class UDPClient {
    public static void main(String[] args) throws IOException {
        //建立入口
        DatagramSocket socket = new DatagramSocket(9998);
        //准备发送数据包
        byte[] contextByte = "今晚吃火锅!".getBytes();
        DatagramPacket packet =
                new DatagramPacket(contextByte,contextByte.length, InetAddress.getByName("192.168.1.18"), 9999);
        //发送数据
        socket.send(packet);

        //准备接收数据包
        byte[] bytes = new byte[1024];
        DatagramPacket packetReceive = new DatagramPacket(bytes, bytes.length);
        //等待接收数据
        socket.receive(packetReceive);
        //输出数据(拆包)
        String context = new String(packetReceive.getData(), 0, packetReceive.getLength());
        System.out.println(context);

        //关闭资源
        socket.close();
    }
}
posted @   邵泽龙  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示