TCP网络编程

180 阅读4分钟

基于Socket的TCP编程

Java语言的基于套接字编程分为服务端编程和客户端编程,其通信模型如图所示:

image.png

客户端Socket的工作过程包含以下四个基本的步骤:

  • 创建Socket:根据指定服务端的 IP 地址或端口号构造 方法Socket()构造 类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
  • 打开连接到 Socket 的输入/出流: 使用getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输.
  • 按照一定的协议对Socket 进行读/写操作:通过输入流读取服务器放入线路的信息 (但不能读取自己放入线路的信息),通过输出流将信息写入线程。
  • 关闭 Socket:断开客户端到服务器的连接,释放线路

服务器程序的工作过程包含以下四个基本的步骤:

  • 调用ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
  • 调用accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信 套接字对象。
  • 调用 该Socket类对象的 getOutputStream() getInputStream ():获取输出流和输入流,开始网络数据的发送和接收。
  • 关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。

image-20201031202038814

客户端发送信息给服务端,服务端将数据显示在控制台上

image.png

先启动客户端报错。TCP需要建立连接。所以要先启动服务端在启动客户端。

image-20201031201448787

2020-10-31 19.33.27


public class TCPTest1 {

    //客服端
    @Test
    public void client() throws IOException {
        //1.创建Socket对象,指明服务器的ip和端口号 本机ip
        InetAddress localHost = InetAddress.getLocalHost();//获取本机ip InetAddress对象
        InetAddress inet = InetAddress.getByName("192.168.1.1");//通过本机ip 获取InetAddress对象
        Socket socket = new Socket(localHost, 8899);
        //2.获取输出流,用于输出数据
        OutputStream os = socket.getOutputStream();
        //3.写出数据
        os.write("你好我是客户端".getBytes());

        //4.关闭资源
        os.close();
        socket.close();
    }

    //服务端
    @Test
    public void server() throws IOException {
        //1.创键SocketServer对象
        ServerSocket serverSocket = new ServerSocket(8899);
        //2.调用accept()表示接受客户端的socket
        Socket socket = serverSocket.accept();
        //3.获取输入流
        InputStream is = socket.getInputStream();
        //4.读取输入流中的数据
        byte[] buffer = new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){
            String str = new String(buffer, 0, len);
            System.out.print(str);
        }
        //5.关闭资源
        is.close();
        socket.close();
        serverSocket.close();
    }
}

客户端发送文件给服务端,服务端将文件保存在本地。

image-20201031195408714

socket.shutdownOutput();

image-20201031195506716

public class TCPTest2 {
    //这里涉及到的异常,应该使用try-catch-finally处理
    @Test
    public void client() throws IOException {
        //1.创建Socket对象,指明服务器的ip和端口号 本机ip
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
        //2.获取输出流,用于输出数据
        OutputStream os = socket.getOutputStream();
        //3.创建文件输入流
        FileInputStream fis = new FileInputStream(new File("wallhaven-39dxld.jpg"));
        //4.读写文件
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);
        }
        //5.资源关闭
        fis.close();
        os.close();
        socket.close();
    }
    @Test
    public void server() throws IOException {
        //1.创键SocketServer对象
        ServerSocket ss = new ServerSocket(9090);
        //2.调用accept()表示接受客户端的socket
        Socket socket = ss.accept();
        //3.获取输入流
        InputStream is = socket.getInputStream();
        //4.创建文件输出流
        FileOutputStream fos = new FileOutputStream(new File("copy.jpg"));
        //5.读写文件
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }
        //6.关闭资源
        fos.close();
        is.close();
        socket.close();
        ss.close();
    }
}

从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。

image-20201031201213160

image-20201031201308671

/**
 * 实现TCP的网络编程
 * 例题3:从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。
 * 并关闭相应的连接。
 */
public class TCPTest3 {
    // 这里涉及到的异常,应该使用try-catch-finally处理
    @Test
    public void client() throws IOException {
        //1.
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
        //2.
        OutputStream os = socket.getOutputStream();
        //3.
        FileInputStream fis = new FileInputStream(new File("copy.jpg"));
        //4.
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }
        //关闭数据的输出
        socket.shutdownOutput();
        //5.接收来自于服务器端的数据,并显示到控制台上
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] bufferr = new byte[20];
        int len1;
        while ((len1 = is.read(buffer)) != -1) {
            baos.write(buffer, 0, len1);
        }
        System.out.println(baos.toString());
        //6.
        fis.close();
        os.close();
        socket.close();
        baos.close();
    }

    @Test
    public void server() throws IOException {
        //1.
        ServerSocket ss = new ServerSocket(9090);
        //2.
        Socket socket = ss.accept();
        //3.
        InputStream is = socket.getInputStream();
        //4.
        FileOutputStream fos = new FileOutputStream(new File("copy2.jpg"));
        //5.
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }
        System.out.println("图片传输完成");
        //6.服务器端给予客户端反馈
        OutputStream os = socket.getOutputStream();
        os.write("发送成功!!".getBytes());

        //7.关闭资源
        fos.close();
        is.close();
        socket.close();
        ss.close();
        os.close();
    }
}