会员可以在此提问,百战程序员老师有问必答
对大家有帮助的问答会被标记为“推荐”
看完课程过来浏览一下别人提的问题,会帮你学得更全面
截止目前,同学们一共提了 133544个问题
Python 全系列/下架-第十二阶段:Python_大型电商项目(5天后下架)/Django项目阶段-电商项目(旧) 30676楼

1.png

为啥p1是self,p2是other,p1p2不应该都是self.name吗

Python 全系列/第一阶段:Python入门/面向对象 30677楼

1.png

老师,我问一下我圈红的那个圈应该怎么弄

Python 全系列/第一阶段:Python入门/面向对象 30678楼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义右击菜单案例</title>
    <style>
        *{padding: 0;margin: 0}
        ul{
            list-style: none;
            background-color: darkgray;
            min-width: 220px;
            display: inline-block;
            position: absolute;
            display: none;
        }
        ul li{
              height: 30px;
              line-height: 30px;
              padding:5px 20px;
              cursor: pointer;
            transition: 0.3s;

        }
        ul li:hover{
            background-color: olivedrab;
            color: #fff;
        }
    </style>
</head>
<body>
<ul>
    <li>北京尚学堂</li>
    <li>欢迎你</li>
    <li>去百度搜索页面中选中的内容</li>
    <li>赚大钱</li>
</ul>
<textarea cols="80" rows="20"></textarea>
<script>
    var ul=document.querySelector("ul");
    document.oncontextmenu=function (eve) {
        return false;//表示事件禁用
    }
    document.onmouseup=function (eve) {
    //eve.button能够判断鼠标用的是哪个按钮
        //0左键  1滑轮 2邮件
        if (eve.button==2){
         ul.style.display="inline-block";
         //设置鼠标点击的位置
            ul.style.left=eve.clientX+"px";
            ul.style.top=eve.clientY+"px";
        }else {
            //关闭菜单
            ul.style.display="none";
        }
    }
    //点击某一菜单选项时触发的事件(事件委托)
    ul.onmousedown=function (eve) {
     if (eve.target.innerHTML=='北京尚学堂'){
        alert("那就去吧");
     }else if (eve.target.innerHTML=='欢迎你') {
         if (confirm('欢迎你?')) {
             window.close();}
     }else if (eve.target.innerHTML=='去百度搜索页面中选中的内容'){
             var result=document.getSelection().toString();
             window.open('http://www.baidu.com/s?wd='+result);
         }else {
         var result=prompt("输入内容然后去百度");
         window.open('http://www.baidu.com/s?wd='+result);
     }
    }
</script>
</body>
</html>

老师我写的这个怎么不跳转百度?为什么要变成字符串的形式?8.jpg

WEB前端全系列/第二阶段:JavaScript编程模块/面向对象编程 30679楼
JAVA 全系列/第一阶段:AI驱动的JAVA编程/面向对象详解和JVM底层内存分析 30680楼
Python 全系列/第四阶段:函数式编程和核心特性/生成器和装饰器 30681楼
JAVA 全系列/第八阶段:Linux入门到实战/Linux(旧) 30683楼
WEB前端全系列/第二阶段:JavaScript编程模块/面向对象编程 30684楼

以下是我自己对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 基础深化和提高/网络编程(旧) 30688楼

课程分类

百战程序员微信公众号

百战程序员微信小程序

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