网络多线程-基础知识

一、TCP字节流

要求:客户端发送一条消息,服务端接收并打印出来
思路:服务端要先监听某个端口,等待客户端的连接(处于阻塞状态);客户端需要知道自己是跟谁通信,要知道对方的IP及端口号,
客户端发送肯定就是把消息输出,用OutputStram
服务端是接收发送来的信息,用 InputStram

注意:要先启动服务端,自己家的大门都没打开,客人怎么可能进得去

client

public class SocketTCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("你好啊".getBytes());
        socket.close();
        outputStream.close();
    }
}

Server

public class SocketTCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);  //端口号可以随意,1024下是系统都使用过了,1024-65535可以使用(不能使用被占用的)
        System.out.println("服务端在9999端口等待连接");
        Socket socket = serverSocket.accept();
        System.out.println("连接成功");
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=inputStream.read(buf)) != -1) {
            System.out.println(new String(buf,0,len));
        }
        socket.close();
        inputStream.close();
    }
}

ServerSocket.accept()是监听9999端口,有人是否连接。当然访问服务器的不止一个,每个连接都是独立的

Scoket s1 = serverSocket.accept();
Scoket s2 = serverSocket.accept();
Scoket s3 = serverSocket.accept();

如果在上一个的基础上,服务端接收到客户端的数据后,返回给客户端一条信息,并打印出来。
如果只是在服务端添加socket.getOutputStream(),客户端添加socket.getInputStream的话,启动后服务端就会一直处于读取状态,客户端也会一直在读取状态,没有结束的标记。双方都在等待对方说话,也不知道是不是说完了。
可以write完成后使用socket.shutDownOutPut()来标记已经发送结束了

二、字符流

在idea中输入socket. 会显示所有方法,但是我们发现只能获取字节流对象,所有要用到IO中的 InputStreamReaderOuputStreamWriter进行转换
发送后,插入换行符,并手动刷新

Client

public class SocketTCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("你好啊,服务器");
        bufferedWriter.newLine(); //插入换行符,代表写入的内容结束
        bufferedWriter.flush(); //需要手动刷新,否则无法写入数据管道
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        System.out.println(bufferedReader.readLine());
        bufferedReader.close();
        bufferedWriter.close();
        socket.close();
    }
}

Server

public class SocketTCP01Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端在9999端口等待连接");
        Socket socket = serverSocket.accept();
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        System.out.println(bufferedReader.readLine());
        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("我在回应你,客户端");
        bufferedWriter.newLine();
        bufferedWriter.flush();
        bufferedWriter.close();
        socket.close();
        inputStream.close();
        serverSocket.close();
    }
}

UDP网络通信原理

DatagramSocketDatagramPacket 实现了基于UDP协议网络程序,UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据包一定能够安全到达目的地,也不确定什么时候可以抵达。DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。

基本流程

  1. 核心的两个类/对象 DatagramSocket和DatagramPacket
  2. 建立发送端、接收端
  3. 建立数据包
  4. 调用DatagramSocket的发送和接收
  5. 关闭DatagramSocket

程序A

public class UDPA {
    public static void main(String[] args) throws IOException {
        //给小B发信息
        DatagramSocket datagramSocket = new DatagramSocket(7777);
        byte[] bytes = "你好啊,小B".getBytes();
        DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),8888); //后两个参数是对方的地址和端口
        datagramSocket.send(datagramPacket);
        //接收小B回来的信息
        datagramSocket.receive(datagramPacket);
        int length = datagramPacket.getLength();
        byte[] data = datagramPacket.getData();
        System.out.println(new String(data,0,length));
        datagramSocket.close();
    }
}

程序B


public class UDPB {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(8888);
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf,buf.length);
        //等待数据
        //将接收到的包填充到 packet
        datagramSocket.receive(packet);
        //将 packet进行拆包,取出数据
        byte[] data = packet.getData();
        //取出数据实际长度
        int length = packet.getLength();
        System.out.println(new String(data,0,length));
        //给小A回信息
        packet.setAddress(InetAddress.getLocalHost()); //设置对方地址
        packet.setPort(7777);  // 设置对方端口
        byte[] bytes = "你好,小A".getBytes();
        packet.setData(bytes,0,bytes.length);
        datagramSocket.send(packet);
        datagramSocket.close();
    }
}

注意:要先启动B,再启动A,不然就会阻塞,如果先启动A,A给B发消息,B还未启动,相当于无效,后面启动B时,B就一直在第一步的等待A数据,A就处于第二步的等待B数据

posted @   jiaxinZz  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
点击右上角即可分享
微信分享提示