光之使者 发表于 2023-7-19 16:39:14

网络编程 p4 TCP编程

TCP编程


[*]基本介绍

[*]基于客户端——服务端的网络通信;
[*]底层使用的是TCP/IP协议;
[*]应用场景举例:客户端发送数据,服务端接收并显示在控制台;
[*]基于Socket的TCP编程;

[*]示意图
https://img2023.cnblogs.com/blog/3008601/202307/3008601-20230719160455615-907466886.png

[*]netstat指令

[*]netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况;
[*]netstat -an|more可以分页显示;
[*]要求在dos控制台下执行 (win+r)
说明:

[*]Listening 表示某个端口在监听;
[*]如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息;

https://img2023.cnblogs.com/blog/3008601/202307/3008601-20230719160513984-1516095100.png

[*]注意事项

[*]当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这端口是TCP/IP来分配的,是随机的;
https://img2023.cnblogs.com/blog/3008601/202307/3008601-20230719160640179-96330720.png

[*]应用案例
https://img2023.cnblogs.com/blog/3008601/202307/3008601-20230719160523918-1093706817.png

[*]客户端
package com.hspedu.socket;

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

/**
* @author: 86199
* @date: 2023/5/15 15:18
* @description: 字符流
*/
public class SocketTCP03Client {
    public static void main(String[] args) throws IOException {
      //思路
      //1. 连接服务端(ip,端口)
      //解读:连接本机的 9999 端口,如果连接成功,返回Socket对象
      Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
      System.out.println("客户端 socket返回 = " + socket.getClass());
      //2. 连接上后,生成Socket,通过socket.getOutputStream()
      //得到和socket对象关联的输出流对象
      BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
      //3. 通过输出流,写入数据到 数据通道
      bufferedWriter.write("hello, server");
      bufferedWriter.newLine();//写入一个换行符,表示写入内容结束,要求对方使用readLine的方式来读
      bufferedWriter.flush();//如果使用的字符流,需要手动刷新否则数据不会写入数据通道


      //4. 通过socket.个体InputStream()读取客户端写入到数据通道的数据,显示
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      String s = bufferedReader.readLine();
      System.out.println(s);

      //5. 关闭流对象和socket,必须关闭
      bufferedReader.close();
      bufferedWriter.close();
      socket.close();

    }
}
[*]服务端
package com.hspedu.socket;

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

/**
* @author: 86199
* @date: 2023/5/15 15:18
* @description: 字符流
*/
public class SocketTCP03Server {
    public static void main(String[] args) throws IOException {
      //思路
      //1. 在本机的9999端口监听,等待连接
      //   细节:要求本机没有其他服务在监听9999
      //   这个 ServerSocket 可以通过accept() 返回多个Socket[多个客户端连接服务器的并发]
      ServerSocket serverSocket = new ServerSocket(9999);
      System.out.println("服务端,在9999端口监听,等待连接...");
      //2. 当没有客户端连接9999端口时程序会阻塞,等待连接
      //   如果有客户端连接,则会返回Socket对象,程序继续
      Socket accept = serverSocket.accept();

      System.out.println("服务端 socket = " + accept.getClass());

      //3. 通过socket.个体InputStream()读取客户端写入到数据通道的数据,显示
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));//读不到内容会阻塞
//4. IO读取
      String s = bufferedReader.readLine();
      System.out.println(s);



      //5. 通过输出流,写入数据到 数据通道
      BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
      bufferedWriter.write("hello, client");
      bufferedWriter.newLine();//写入一个换行符,表示写入内容结束,要求对方使用readLine的方式来读
      bufferedWriter.flush();//如果使用的字符流,需要手动刷新否则数据不会写入数据通道
      //设置结束标记

      //6. 关闭流对象和socket,必须关闭
      bufferedWriter.close();
      bufferedReader.close();
      accept.close();
      serverSocket.close();
    }
}
https://img2023.cnblogs.com/blog/3008601/202307/3008601-20230719160540831-1759295270.png

[*]StreamUtils类
package com.hspedu.upload;

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

/**
* @author: 86199
* @date: 2023/5/16 14:57
* @description: 工具类
*/
public class StreamUtils {
    public static byte[] streamToByteArray(InputStream is) throws Exception {
      // 创建输出流对象
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      // 字节数组
      byte[] b = new byte;
      int len;
      while ((len = is.read(b)) != -1) {
            // 循环读取
            // 把读取到的数据,写入 bos
            bos.write(b, 0, len);
      }
      byte[] array = bos.toByteArray();
      bos.close();
      return array;
    }

    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();
    }
}
[*]服务端
package com.hspedu.upload;

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

/**
* @author: 86199
* @date: 2023/5/15 16:24
* @description:
*/
public class TCPFileUploadServer {
    public static void main(String[] args) throws Exception {
      ServerSocket serverSocket = new ServerSocket(8888);
      System.out.println("服务端在8888等待连接......");
      Socket accept = serverSocket.accept();

      String filePath = "D:\\program\\javaProject\\Idea_Java_Project\\chapter21\\src\\copy.jpg";

      BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));

      byte[] bytes = StreamUtils.streamToByteArray(bis);

      bos.write(bytes);
      bos.close();

      //向客户端回复“收到图片”
      BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
      bufferedWriter.write("收到图片");
      bufferedWriter.flush();
      accept.shutdownOutput();

      //关闭流和socket
      bis.close();
      accept.close();
      serverSocket.close();
    }
}
[*]客户端
package com.hspedu.upload;

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


/**
* @author: 86199
* @date: 2023/5/15 16:24
* @description:
*/
public class TCPFileUploadClient {
    public static void main(String[] args) throws Exception {

      Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
      String filePath = "e:\\qie.jpg";

      BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
      BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));

      byte[] bytes = StreamUtils.streamToByteArray(bis);
      bos.write(bytes);
      bos.flush();
      //没有手动调用flush方法,也没有调用close方法关闭流,数据复制失败,
      //因为数据还在内部缓冲区,并没有输出 (因为内部缓冲区没有被放满,不调用flush方法,不会输出)
      bis.close();
      socket.shutdownOutput();

      //接收消息
      InputStream inputStream = socket.getInputStream();
      String s = StreamUtils.streamToString(inputStream);
      System.out.println(s);

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


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 网络编程 p4 TCP编程