会员可以在此提问,百战程序员老师有问必答
对大家有帮助的问答会被标记为“推荐”
看完课程过来浏览一下别人提的问题,会帮你学得更全面
截止目前,同学们一共提了 132904个问题

以下是我自己对UDP 一个发送者与一个接受者,多次咨询,双方互相发送的代码的优化,参考TCP的多线程

首先是Clinet项目

为一个发送者建立两个线程类,一个Send类,一个Receive类。用于发送和接收。

Send类

package com.gz.udp2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Scanner;

public class Send implements Runnable{
    private DatagramSocket ds;
    private Scanner sc;
    private String destIp;//目标ip
    private int destPort;//目标端口号
    private String role;//角色名称
    private boolean flag=true;


    public Send(DatagramSocket ds,String destIp,int destPort,String role) {
        this.ds = ds;
        this.destIp=destIp;
        this.destPort=destPort;
        this.role=role;
        sc=new Scanner(System.in);
    }
    private String getMessage(){
        return sc.next();
    }
    private void send(String str){
        //发送时间
        String date=new Date().toLocaleString();
        str=date+"   "+role+":"+str;
        byte[] buf=str.getBytes();
        try {
            DatagramPacket dp=new DatagramPacket(buf,buf.length, InetAddress.getByName(destIp),destPort);
            ds.send(dp);
        } catch (IOException e) {
            flag=false;
            if(ds!=null) {
                ds.close();
            }
        }
    }

    @Override
    public void run() {
        while(flag){
            this.send(this.getMessage());
        }

    }
}

Receive类

package com.gz.udp2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Scanner;

public class Receive implements Runnable{

    private DatagramSocket ds;
    private Scanner sc;
    private boolean flag=true;

    public Receive(DatagramSocket ds) {
        this.ds = ds;
        sc=new Scanner(System.in);
    }
    private String receive(){
        String str="";
        try {
            byte [] buf=new byte[1024];//等待接收数据
            DatagramPacket dp=new DatagramPacket(buf,buf.length);
            ds.receive(dp);
            str=new String(dp.getData(),0,dp.getLength());
        } catch (IOException e) {
            flag=false;
            if(ds!=null){
                ds.close();
            }
        }
        return str;
    }

    @Override
    public void run() {
        while(flag){
            System.out.println(this.receive());
        }
    }
}

Test1类,开启线程的类

package com.gz.udp2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Test1 {
    public static void main(String[] args) throws IOException {
        //DS
        DatagramSocket ds=new DatagramSocket(9777);//自己的端口号

        Send s=new Send(ds,"localhost",9888,"咨询者");
        //目标ip,目标端口号,自己角色
        Receive r=new Receive(ds);

        new Thread(s).start();
        new Thread(r).start();


    }
}


对于接收者,也是拥有两个类,Send类和Receive类,及同样的开启线程类,只不过是端口号不同,角色不同。

接收者的Test2类

package com.gz.udp2;

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

public class Test2 {
    public static void main(String[] args) throws IOException {
        //DS
        DatagramSocket ds=new DatagramSocket(9888);

        Send s=new Send(ds,"localhost",9777,"客服人员");
        //目标ip,目标端口号,自己角色
        Receive r=new Receive(ds);

        new Thread(s).start();
        new Thread(r).start();


    }
}


结果:成功实现了,客服多次回复:又优化加上了发送时间:

咨询者端:

image.png

客服端:

image.png


想让老师看一下我的代码还有哪里值得优化,还有一个问题,就是,单对单的时候,接收者在回复的时候可以获得发送者发送来的ip与端口号,但是我现在写成了多线程,并且在我的发送者与接收者的测试类里,ip跟端口号是单独指定的,也就是说,当线程开启之前,ip与端口号就固定下来了,下面的交互都是这两个ip与端口号之间的交互。我想问的是有办法像单对单那样,获取到上一个接收过来的数据来自的ip和端口号吗,这样的话就要找到上一个接收线程的DatagramPacket数据包dp,从dp能够获取到上一个发送端的ip及端口号,可是由于多线程,我编辑的逻辑是,每次接收和发送的方法都会创建新的DatagramPacket,当上一个线程调用发送方法以后,随着方法结束,dp数据包也会随之在内存中释放消失。所以,我觉得是完不成根据dp获取上一个发送端的ip及端口号的。因此这也是我的发送端和接收端都要重新制定ip及端口号的原因。

思考到这,(小总结******)我在想UDP是不是就是适合于两个人在通信的时候进行的交互,比如qq聊天,客服聊天,并且这两个人的聊天是指定两个人的单次会话的多次聊天。

而TCP适合群聊,中间的服务器可以将信息转发给其他人,也可以满足随时有人加入群聊,为随时加入群聊的客户端开启处理线程。


以上是我的思考,不知道有没有误解,想跟老师求证最后说的总结(带******号的)的正确性。

还有上面多线程的代码是否可以进一步优化,以及我对我的程序中发送端和接收端都要重新制定ip及端口号的理解是否正确。

还有就是UDP的单次会话的多线程如果真的实现是不是像我写的那样的,发送端和接收端都要重新制定ip及端口号。

JAVA 全系列/第二阶段:JAVA 基础深化和提高/网络编程(旧) 30618楼
Python 全系列/第一阶段:Python入门/控制语句 30623楼
Python 全系列/第一阶段:Python入门/控制语句 30624楼
Python 全系列/第十四阶段:Python 爬虫开发/爬虫数据存储 30626楼
Python 全系列/第五阶段:数据库编程/mysql的使用 30627楼

代码运行报错:KeyError: 'formatters'

完整报错代码:

(flask_shop) PS C:\python\bzcxy\dijiujieduan> python .\manager.py db migrate
Traceback (most recent call last):
  File ".\manager.py", line 12, in <module>
    manager.run()
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\flask_script\__init__.py", line 417, in
    result = self.handle(argv[0], argv[1:])
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\flask_script\__init__.py", line 386, in
    res = handle(*args, **config)
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\flask_script\commands.py", line 216, in
    return self.run(*args, **kwargs)
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\flask_migrate\__init__.py", line 96, in
    f(*args, **kwargs)
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\flask_migrate\__init__.py", line 212, i
    version_path=version_path, rev_id=rev_id)
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\alembic\command.py", line 214, in revis
    script_directory.run_env()
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\alembic\script\base.py", line 489, in r
    util.load_python_file(self.dir, "env.py")
  File "D:\Python_VirtualEnv\flask_shop\lib\site-packages\alembic\util\pyfiles.py", line 98, in l
    module = load_module_py(module_id, path)
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "migrations\env.py", line 17, in <module>
    fileConfig(config.config_file_name)
  File "c:\users\quanz\appdata\local\programs\python\python37\lib\logging\config.py", line 71, in fileConfig
    formatters = _create_formatters(cp)
  File "c:\users\quanz\appdata\local\programs\python\python37\lib\logging\config.py", line 104, in _create_formatters
    flist = cp["formatters"]["keys"]
  File "c:\users\quanz\appdata\local\programs\python\python37\lib\configparser.py", line 958, in __getitem__
    raise KeyError(key)
KeyError: 'formatters'

我觉得应该是环境配置的问题,代码应该没问题,我刚把python卸载重装了一下,结果还是报错,希望老师能解决一下。

dijiujieduan.zip


Python 全系列/第九阶段:Flask百战电商后台系统/Flask百战电商后台项目 30628楼

课程分类

百战程序员微信公众号

百战程序员微信小程序

©2014-2025百战汇智(北京)科技有限公司 All Rights Reserved 北京亦庄经济开发区科创十四街 赛蒂国际工业园
网站维护:百战汇智(北京)科技有限公司
京公网安备 11011402011233号    京ICP备18060230号-3    营业执照    经营许可证:京B2-20212637