网络编程---使用UDP与多线程,实现聊天功能(详细大全)

若使用网络编程UDP实现聊天功能,我们首先要创建两个线程

    线程1:发送消息的线程

    线程2:接受消息的线程

除此之外,我们还需要两个用户来进行互相沟通(互相传递信息)

    用户1:发送和接受信息

    用户2: 发送和接受信息

   

    用户1向用户2发送信息:

       从用户1端口--->根据IP+对方的端口号 定位到具体的人--->用户2接受到消息

    用户2向用户1发送信息:

       从用户2端口--->根据IP+对方的端口号 定位到具体的人--->用户1接受到消息

一、发送消息的线程

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

//用这个模仿发送消息
public class ChatSend implements  Runnable{
    DatagramSocket socket = null;
    BufferedReader reader = null;

//     我们只有知道了对方的 端口和 ip才可以访问到具体的那个人
    private String toIP;    //对方的端口
    private  int toPort;    //对方的ip

     private int fromPort;  //自己的端口  也就是说我们从这个端口发出的信息

    public ChatSend(String toIP, int toPort, int fromPort) {
        this.toIP = toIP;
        this.toPort = toPort;
        this.fromPort = fromPort;

        try {
//      1.建立一个Socket 对象,我们要使用这个对象的sent方法发送信息
            socket = new DatagramSocket(this.fromPort);  //this.fromPort 是发送消息的端口号
//                 这个流备用,目的就是 从 控制台读取我们想要发送的信息(读取聊天内容)
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try{
            while (true){
//      2.读取控制台的信息      (返回一个字符串对象)
                String msg = reader.readLine();
//      3.建立一个包
//                  InetAddress不能new出来,没有构造器,只能用静态方法返回回来(因为这些静态方法的返回对象就是InetAddress类型的)
                InetAddress localhost = InetAddress.getByName(this.toIP);
//                  msg.getBytes():传递消息的字节数组    0:起始位置    msg.getBytes().length:字节数组的长度(所打包的长度)
//                  localhost、port :要发送给谁,具体的IP,具体的地址
                DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,this.toPort);

//      4.发送包(发送消息)
                socket.send(packet);
//      5.根据接发送的信息,判断是否需要断开连接
                if("bye".equals(msg)){
//                     本地推出
                    System.out.println("聊天结束!!!!!");
                    break;
                }
            }
//         关闭
            socket.close();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、接受消息的线程

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

// 用这个 模仿接收消息
public class ChatReceive implements Runnable {
    DatagramSocket socket = null;

    private  int port; //自己的端口号   也就是说我们在这个端口收集到的信息
    private  String receivedBy; // 这个信息从哪里来

    public ChatReceive(int port,String receivedBy) {
        this.port = port;
        this.receivedBy = receivedBy;

        try {
//      1.建立一个Socket 对象,我们要使用这个对象的receive方法接收信息
            socket = new DatagramSocket(this.port);
        } catch (SocketException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {


        try {
            while(true){
//      2. 准备接受包裹
                byte[] bytes = new byte[1024];
                DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
//      3.接收包
                socket.receive(packet);//阻塞式接收包裹
//      4.转义包的信息并在控制台中输出
                byte[] msgBytes = packet.getData();
//                     packet.getData()方法获取的是 byte数组形式的数值,我们需要把byte数组转化成字符串的形式让别人阅读
//                     这里的参数的意思:将字节数组msgBytes从下标为0的开始,一直到下标packet.getLength()的字节结束,将其转化为字符串
                String msg = new String(msgBytes,0, packet.getLength());
                System.out.println("received by "+receivedBy+":"+msg);

//      5.根据接收到的信息,判断是否需要断开连接          bye 是断开连接
                if("bye".equals(msg)){
                    System.out.println("聊天结束!!!!!!");
                    break;
                }

            }
            socket.close();  //断开断开

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、交流对象1

public class Teacher {
    public static void main(String[] args) {
//  开启两个线程
//      1.发送消息的线程
//                    第一个参数是我们要把信息发送到哪个IP上  第二个参数:我们要把信息发送到哪个端口上   第三个参数:我们自己的端口是什么
//                      从我们的5555端口发送到localhost:8888端口,(因为另一个人用8888接口接受消息)
        Thread t1 = new Thread(new ChatSend("localhost",8888,5555));
//      2.接收消息的线程
//                    第一个参数是端口号,第二个参数是 消息的来源是谁
//                        我们用9999端口接受消息
        Thread t2 = new Thread(new ChatReceive(9999,"学生"));
//      3.启动线程
        t1.start();
        t2.start();

    }
}

四、交流对象2

public class Student {
    public static void main(String[] args) {
//        开启两个线程
//      1.发送消息的线程
//                    第一个参数是我们要把信息发送到哪个IP上  第二个参数:我们要把信息发送到哪个端口上   第三个参数:我们自己的端口是什么
//                    从 我们的7777端口发送到localhost:9999端口  (因为另一个人用9999端口接收消息)
        Thread t1 = new Thread(new ChatSend("localhost",9999,7777));

//      2.接收消息的线程
//                    第一个参数是端口号,第二个参数是 消息的来源是谁
//                    我们用8888端口接受消息
        Thread t2 = new Thread(new ChatReceive(8888,"老师"));
//      3.启动线程
        t1.start();
        t2.start();


    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我爱布朗熊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值