Java网络编程 08 多线程实现双人聊天

3.1 多线程实现双人聊天


  1. 首先要想清楚,为什么 要多线程 实现 双人的 聊天。而不是用 线程 去写!!!

单线程的话,我们只能够 方便的操作 一个功能(发送 / 接收),即使 你把 发送 和 接收 写在 一起!甚至是 经过了 死循环 和 标识判断,实现了 两种功能 的切换,但在效率上 也是很低的。(并不是 不能做到!而是 很复杂,很不方便,即使实现了,效率也很低!)我一开始 学习 网络编程 就尝试 写过 一个 主线程 写 接收 和 发送 功能,可以写。但是 特别的麻烦,效率还低下。

  1. 如果可以实现,那么应该 主要的核心点是什么 ?

是可以实现的,不过需要注意的是,必须在 UDP 协议下 使用 四个 端口!这是为什么呢 ? 也不是必须。。只是 让其 不产生 不必要的冲突!!我们的端口那么多。开四个 没啥事。


这四个 端口的 分配是:
聊天者A:自身发送端口、目标接收端口、自身接收端口。
聊天者B:自身发送端口、目标接收端口、自身接收端口。
总计:目标接收端口 *2 + 自身发送 端口 * 2 一共是 4个 端口。这样 就可以保证,我跟你 断开连接,断开的是 我的发送和你的接收 端口!这个时候 你还可以 跟我 发送 信息。就证明 这种 4 个 端口的方式 是非常的 稳定的!!!

代码很简单,只要 简单的学习过 JavaThread 就可以 写出来。基本上 就是 面向 CV(复制粘贴) 的编程工作。

  • 发送信息事务(要用线程 启动
package www.muquanyu.lesson03;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class ReseiveThread implements Runnable{

    private int fromPort;//就是自己的 端口
    private DatagramSocket socket = null;

    public ReseiveThread (int fromPort) throws SocketException {
        socket = new DatagramSocket(fromPort);
    }


    @Override
    public void run() {
        while(true)
        {
            //创建接收数据包
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container, 0,container.length);


            //接收 数据包
            try {
                socket.receive(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }

            byte[] data = packet.getData();
            System.out.println(getSize(data));
            String dataString = new String(data,0,getSize(data));
            if(dataString.equals("bye"))
            {
                break;
            }
            dataString = "接收到了msg:"+ dataString;
            System.out.println(dataString);

        }
        socket.close();
        System.out.println(fromPort+":UDP协议已关闭");
    }

    public static int getSize(byte[] data) {
        int i = 0;
        for (byte x : data) {
            if (x != (byte) 0) {
                i++;
            }
        }
        return i;
    }
}
  • 接收信息事务(要用线程启动
package www.muquanyu.lesson03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

public class SendThread implements Runnable {

    private int fromPort;//自己的 端口
    private int toPort;//目标的 端口
    private InetAddress address = null;//目标的 IP 地址
    private DatagramSocket socket = null;

    public SendThread(String address,int fromPort, int toPort) throws UnknownHostException, SocketException {
        this.fromPort = fromPort;
        this.toPort = toPort;
        this.address = InetAddress.getByName(address);
        this.socket = new DatagramSocket(fromPort);
    }

    @Override
    public void run() {
        while(true)
        {
            //准备数据:控制台读取 System.in
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

            String data = null;
            try {
                data = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            byte[] datas = data.getBytes();
            DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(address, toPort));

            try {
                socket.send(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(data.equals("bye"))
            {
                break;
            }
        }
        socket.close();
        System.out.println(fromPort+":UDP协议已关闭");
    }

}

接下来 就是 直接 调用 咱们写的 线程事务,来进行 线程的启动就行了。

我们可以再创建 两个 类,分别代表 聊天者 A 和 聊天者 B。它们各自 都启动 两个线程,总计 四个线程!!(效率是极高的。)

  • 聊天者 A
package www.muquanyu.lesson03;

import java.net.SocketException;
import java.net.UnknownHostException;

public class SenderA {
    public static void main(String[] args) throws SocketException, UnknownHostException {
        ReseiveThread reseiveThread = new ReseiveThread(8888);
        SendThread sendThread = new SendThread("localhost",6666, 9999);
        new Thread(reseiveThread).start();
        new Thread(sendThread).start();
    }
}
  • 聊天者 B
package www.muquanyu.lesson03;

import java.net.SocketException;
import java.net.UnknownHostException;

public class SenderB {
    public static void main(String[] args) throws SocketException, UnknownHostException {
        ReseiveThread reseiveThread = new ReseiveThread(9999);
        SendThread sendThread = new SendThread("localhost",7777, 8888);
        new Thread(reseiveThread).start();
        new Thread(sendThread).start();
    }
}

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值