问答详情
源自:4-3 编程实现基于 UDP 的 Socket 通信之客户端

UDP编程,使用多线程的时候为什么在run方法中获取不到值?

如图:我将接受到的packet传过来后,在构造方法中能够获取对应的值(可以看到通过构造方法获取到的port是55419),但是如果要在run方法中获取端口号(第三个红框标记部分)等信息,就获取不到,程序变成阻塞中,没有其他报错信息~

https://img2.mukewang.com/5baa01a80001081908980546.jpg




我的代码如下:

Server:

package com.socket.socketsender.UDPSoceket;

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

public class UDPServer {

    public static void main(String[] args) throws IOException {
        //接收请求
        DatagramSocket socket = new DatagramSocket(8110);//指定服务器端口
        byte[] data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, data.length);//创建数据报,用于接收客户端发送的数据
        System.out.println("========服务器已启动,正在等待客户端发送数据======");
        while (true) {
            socket.receive(packet);//此方法在接收到客户端数据之前会一直阻塞
            new Thread(new ThreadUDPServer(socket, packet)).start();
        }
    }

    private static class ThreadUDPServer implements Runnable {
        private DatagramPacket packet;
        private String info;
        private DatagramSocket socket;
        private InetAddress address;
        private int port;

        public ThreadUDPServer(DatagramSocket socket, DatagramPacket packet) {
            this.socket = socket;
            this.packet = packet;
            this.info = new String(packet.getData(), 0, packet.getLength());//在run方法中获取不到info???
            this.address=packet.getAddress();
            this.port=packet.getPort();
        }
        @Override
        public void run() {
            int test = packet.getPort();
            System.out.println("接收到客户端的消息是:" + info);
            //发送响应信息
            byte[] data2 = "这是服务器的响应信息:登录成功".getBytes();
            DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
            try {
                socket.send(packet2);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


client:

package com.socket.socketsender.UDPSoceket;

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

public class UDPClient {

    public static void main(String[] args) throws IOException {


        try (DatagramSocket socket = new DatagramSocket()) {
            //发送请求
            InetAddress addresses = InetAddress.getByName("localhost");
            byte[] data = "用户名:小王;密码:123456".getBytes();
            int port = 8110;
            DatagramPacket packet = new DatagramPacket(data, data.length, addresses, port);
            byte[] data2 = new byte[1024];
            socket.send(packet);
            //接收响应信息
            DatagramPacket packet2 = new DatagramPacket(data2, 0, data2.length);
            socket.receive(packet2);
            String info = new String(data2,0,packet2.getLength());
            System.out.println("接收到服务器的响应信息:"+info);
        }



    }
}


提问者:杨勤_cd 2018-09-25 17:39

个回答

  • T天涯灬
    2018-10-14 14:42:01
    已采纳

    你的DatagramSocket socket是主线程的东西,新建的其他线程当然用不了,你把sokect放在公共区用volatile修饰让所有线程共享就可以了,亲测。

    代码:

        

    public class UDPServer2 {
    
        public static volatile DatagramSocket socket;//指定服务器端口
    
        static {
            try {
                socket = new DatagramSocket(8110);
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
        public static volatile byte[] data = new byte[1024];
        public static volatile DatagramPacket packet = new DatagramPacket(data, data.length);//创建数据报,用于接收客户端发送的数据
    
        public static void main(String[] args) throws IOException {
            //接收请求
    //        DatagramSocket socket = new DatagramSocket(8110);//指定服务器端口
    //        byte[] data = new byte[1024];
    //        DatagramPacket packet = new DatagramPacket(data, data.length);//创建数据报,用于接收客户端发送的数据
            System.out.println("========服务器已启动,正在等待客户端发送数据======");
            while (true) {
                socket.receive(packet);//此方法在接收到客户端数据之前会一直阻塞
                new Thread(new ThreadUDPServer(socket, packet)).start();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }


  • T天涯灬
    2018-10-14 14:44:02

    还有如要非要用while(true)最好用

    Thread.sleep();

    解放一下cpu,不然没很有可能卡机