Java笔记之网络编程(二十九)

一、InetAddress类和Socket

1.InetAddress类

相关方法

方法名功能
getLocalHost获取本机InetAddress对象
getByName根据指定主机名/域名获取ip地址对象
getHostName获取InetAddress对象的主机名
getHostAddress获取InetAddress对象的地址

快速入门

import java.net.InetAddress;
import java.net.UnknownHostException;

public class test {
    public static void main(String[] args) throws UnknownHostException {
        //获取本机 InetAddress 对象 getLocalHost
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        //根据指定主机名/域名获取 ip 地址对象 getByName
        InetAddress byName = InetAddress.getByName("DESKTOP-RT31TG6");
        System.out.println(byName);

        InetAddress byName1 = InetAddress.getByName("www.baidu.com");
        System.out.println(byName1);
        //获取 byName1 对象的主机名 getHostName
        String hostName = byName1.getHostName();
        System.out.println(hostName);
        //获取 byName1 对象的地址 getHostAddress
        String hostAddress = byName1.getHostAddress();
        System.out.println(hostAddress);
    }
}

2.Socket

基本介绍

Socket开发网络应用程序被广泛采用,以至于称为事实的标准。

  1. 通信的两端都要有Socket,是两台机器通信的端点
  2. 网络通信其实就是Socket间的通信
  3. Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO流进行传输的
  4. 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端

二、TCP网络通信编程

1.基本介绍

  1. 基于客户端—服务端的网络通信
  2. 底层使用的是TCP/IP协议
  3. 应用场景举例:客户端发送数据,服务端接受并显示控制台
  4. 基于Socket的TCP编程

在这里插入图片描述

注意:需先启动服务端,然后再启动客户端

2.应用案例

案例一

要求:

  1. 使用字节流
  2. 编写一个服务器端和客户端
  3. 服务器端在9999端口监听
  4. 客户端连接到服务器端,发送“hello server”,然后退出
  5. 服务器端接收到客户端发送的信息,输出,并退出

服务器Server端

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//服务端
public class SocketTCPServer {
    public static void main(String[] args) throws IOException {
        //在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
        ServerSocket serverSocket= new ServerSocket(9999);
        System.out.println("服务端对9999进行端口监听,等待连接..");
        //等待连接
        //细节:serverSocket可以通过accept()返回多个Socket,多个客户端连接服务器的并发
        Socket socket = serverSocket.accept();
        System.out.println("服务端 socket =" + socket.getClass());

        //通过 socket.getInputStream() 读取客户端写入到数据通道的数据
        InputStream inputStream = socket.getInputStream();

        //再通过IO流进行读取
        byte[] bytes = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(bytes)) != -1){
            System.out.println(new String(bytes,0,readLen));
        }

        //关闭流和socket,必须关闭
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客户端Client

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//客户端
public class SocketTCPClient {
    public static void main(String[] args) throws IOException {
        //连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回为:"+socket.getClass());
        //通过socket.getOutputStream()获取socket 对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //通过IO流,写入数据到数据通道
        outputStream.write("hello server".getBytes());

        //关闭流对象和 socket,必须关闭
        outputStream.close();
        socket.close();
        System.out.println("客户端退出....");
    }
}

案例二

要求:

  1. 使用字节流
  2. 编写一个服务器端和客户端
  3. 服务器端在9999端口监听
  4. 客户端连接到服务器端,发送“hello server”,并接收服务器端回发的 “hello client” 然后再退出
  5. 服务器端接收到客户端发送的信息,输出,并发送“hello client”给客户端,最后再退出

注意:当流写入数据通道后,需要设置结束标记

服务器Server端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//服务端
public class SocketTCPServer {
    public static void main(String[] args) throws IOException {
        //在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
        ServerSocket serverSocket= new ServerSocket(9999);
        System.out.println("服务端对9999进行端口监听,等待连接..");
        //等待连接
        //细节:serverSocket可以通过accept()返回多个Socket,多个客户端连接服务器的并发
        Socket socket = serverSocket.accept();
        System.out.println("服务端 socket =" + socket.getClass());

        //通过 socket.getInputStream() 读取客户端写入到数据通道的数据
        InputStream inputStream = socket.getInputStream();

        //再通过IO流进行读取
        byte[] bytes = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(bytes)) != -1){
            System.out.println(new String(bytes,0,readLen));
        }

        //获取socket相关联的输出流,写入数据到数据通道,使用字节流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello client".getBytes());

        //设置结束标记
        socket.shutdownOutput();

        //关闭流和socket,必须关闭
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客户端Client

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//客户端
public class SocketTCPClient {
    public static void main(String[] args) throws IOException {
        //连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回为:"+socket.getClass());
        //通过socket.getOutputStream()获取socket 对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //通过IO流,写入数据到数据通道
        outputStream.write("hello server".getBytes());

        //设置结束标记
        socket.shutdownOutput();

        //获取socket相关联的输入流,读取数据并显示。使用的字节流
        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));
        }

        //关闭流对象和 socket,必须关闭
        outputStream.close();
        socket.close();
        System.out.println("客户端退出....");
    }
}

案例三

要求:

  1. 使用字符流
  2. 编写一个服务器端和客户端
  3. 服务器端在9999端口监听
  4. 客户端连接到服务器端,发送“hello server”,并接收服务器端回发的 “hello client” 然后再退出
  5. 服务器端接收到客户端发送的信息,输出,并发送“hello client”给客户端,最后再退出

将字节流转换为字符流,需要用到转换流

注意:这里设置结束标记除了使用socket.shutdownOutput();也可以用 如:writer.newLine()设置结束标记,而且对面接收数据需要使用readLine来接收

服务器Server端

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//服务端
public class SocketTCPServer {
    public static void main(String[] args) throws IOException {
        //在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
        ServerSocket serverSocket= new ServerSocket(9999);
        System.out.println("服务端对9999进行端口监听,等待连接..");
        //等待连接
        //细节:serverSocket可以通过accept()返回多个Socket,多个客户端连接服务器的并发
        Socket socket = serverSocket.accept();
        System.out.println("服务端 socket =" + socket.getClass());

        //通过 socket.getInputStream() 读取客户端写入到数据通道的数据
        InputStream inputStream = socket.getInputStream();

        //再通过IO流进行读取,使用字符流读取
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);

        //获取socket相关联的输出流,写入数据到数据通道
        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello client");
        bufferedWriter.newLine();   //插入一个换行符,表示写入的内容结束,但是要求对面使用readLine()进行读取
        bufferedWriter.flush(); //如果使用字符流,则需要手动刷新,否则不会写数据通道

        //关闭流和socket,必须关闭,这里只需要关闭外层流即可,按照先打开后关闭的原则
        bufferedWriter.close();
        bufferedReader.close();
        socket.close();
        serverSocket.close();
    }
}

客户端Client

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//客户端
public class SocketTCPClient {
    public static void main(String[] args) throws IOException {
        //连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回为:"+socket.getClass());
        //通过socket.getOutputStream()获取socket 对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //通过IO流,写入数据到数据通道,这里使用字符流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello server");
        bufferedWriter.newLine();   //插入一个换行符,表示写入的内容结束,但是要求对面使用readLine()进行读取
        bufferedWriter.flush(); //如果使用字符流,则需要手动刷新,否则不会写数据通道

        //获取socket相关联的输入流,读取数据并显示。
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);

        //关闭流对象和 socket,必须关闭,这里只需要关闭外层流即可,按照先打开后关闭的原则
        bufferedReader.close();
        bufferedWriter.close();
        socket.close();
        System.out.println("客户端退出....");
    }
}

2.网络上传文件

案例四

要求:

  1. 编写一个服务器端和客户端
  2. 服务器端在9999端口监听
  3. 客户端连接服务端,发送一张图片 F:\\java.jpeg
  4. 服务器端接收到客户端发送的图片,保存到src下,发送“收到图片”,然后再退出
  5. 客户端接收到服务端发送的“收到图片”,再退出
  6. 需使用一个工具类StreamUtils.java

StreamUtils工具类

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * 此类用于演示关于流的读写方法
 *
 */
public class StreamUtils {
	/**
	 * 功能:将输入流转换成byte[], 即可以把文件的内容读入到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);//把读取到的数据,写入bos	
		}
		byte[] array = bos.toByteArray();//然后将bos 转成字节数组
		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){
			builder.append(line+"\r\n");
		}
		return builder.toString();
		
	}

}

服务器Server端

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//服务端
public class SocketTCPServer {
    public static void main(String[] args) throws Exception {
        //在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
        ServerSocket serverSocket= new ServerSocket(9999);
        System.out.println("服务端对9999进行端口监听,等待连接..");
        //等待连接
        Socket socket = serverSocket.accept();

        //读取客户端发送的数据
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //读取管道传过来的文件字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //将得到的字节数组,写入到指定的路径,得到一个文件
        String newFilePath = "src\\java.jpeg";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFilePath));
        bos.write(bytes);

        //向客户端回复信息,字符流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bufferedWriter.write("收到图片!");
        bufferedWriter.newLine();
        bufferedWriter.flush();

        //关闭资源
        bufferedWriter.close();
        bos.close();
        bis.close();
        socket.close();
        serverSocket.close();
    }
}

客户端Client

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author wangbo
 * @version 1.0
 */
//客户端
public class SocketTCPClient {
    public static void main(String[] args) throws Exception {
        //连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        String filepath = "F://java.jpeg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filepath));

        //把读取的内容转换成字节数组,使用工具类
        byte[] bytes = StreamUtils.streamToByteArray(bis);

        //通过socket获取输出流,将bytes数据发送给服务器
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);   //将文件写入数据通道
        socket.shutdownOutput();

        //接收信息
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);

        bufferedReader.close();
        bos.close();
        bis.close();
        socket.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王博1999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值