Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:多线程&;UDP套接字编程_Java_Multithreading_Sockets_Udp - Fatal编程技术网

Java:多线程&;UDP套接字编程

Java:多线程&;UDP套接字编程,java,multithreading,sockets,udp,Java,Multithreading,Sockets,Udp,我不熟悉Java中的多线程和套接字编程。我想知道实现两个线程的最佳方式是什么——一个用于接收套接字,另一个用于发送套接字。如果我想做的事情听起来很荒谬,请告诉我原因!这段代码主要是从Sun的在线教程中得到启发的。我想使用多播套接字,这样我就可以使用多播组 class Server extends Thread { static protected MulticastSocket socket = null; protected BufferedReader in = null;

我不熟悉Java中的多线程和套接字编程。我想知道实现两个线程的最佳方式是什么——一个用于接收套接字,另一个用于发送套接字。如果我想做的事情听起来很荒谬,请告诉我原因!这段代码主要是从Sun的在线教程中得到启发的。我想使用多播套接字,这样我就可以使用多播组

class Server extends Thread
{

    static protected MulticastSocket socket = null;
    protected BufferedReader in = null;
    public InetAddress group;

    private static class Receive implements Runnable
    {

        public void run()
        {
            try
            {
                byte[] buf = new byte[256];
                DatagramPacket pkt = new DatagramPacket(buf,buf.length);
                socket.receive(pkt);
                String received = new String(pkt.getData(),0,pkt.getLength());
                System.out.println("From server@" + received);          
                Thread.sleep(1000);
            }
            catch (IOException e)
            { 
                System.out.println("Error:"+e);
            }   
            catch (InterruptedException e)
            { 
                System.out.println("Error:"+e);
            }   

        }

    }


    public Server() throws IOException
    {
        super("server");
        socket = new MulticastSocket(4446);
        group = InetAddress.getByName("239.231.12.3");
        socket.joinGroup(group);
    }

    public void run()
    {

        while(1>0)
        {   
            try
            {
                byte[] buf = new byte[256];
                DatagramPacket pkt = new DatagramPacket(buf,buf.length);        
                //String msg = reader.readLine();
                String pid = ManagementFactory.getRuntimeMXBean().getName();
                buf = pid.getBytes();
                pkt = new DatagramPacket(buf,buf.length,group,4446);
                socket.send(pkt);
                Thread t = new Thread(new Receive());
                t.start();

                while(t.isAlive())
                { 
                    t.join(1000);
                }
                sleep(1);
            }
            catch (IOException e)
            { 
                System.out.println("Error:"+e);
            }   
            catch (InterruptedException e)
            { 
                System.out.println("Error:"+e);
            }   

        }
        //socket.close();
    }

    public static void main(String[] args) throws IOException
    {
        new Server().start();
        //System.out.println("Hello");
    }

}

想要在应用程序中创建线程并不荒谬!您不需要确切的2个线程,但我认为您讨论的是实现Runnable接口的2个类

自Java1.5以来,线程API变得更好了,您不再需要再处理Java.lang.Thread了。您只需创建一个并向其提交可运行实例


这本书使用了这个确切的问题——创建一个线程套接字服务器——并对代码进行了多次迭代,以展示实现这一点的最佳方法。查看免费的样本章节,这是伟大的。我不会在这里复制/粘贴代码,但请具体查看清单6.8。

首先要做的是:您的类应该以大写字母开头:

类名应为名词,大小写应与单词的第一个字母混合 每个内部单词都大写。尝试 保持你的类名简单明了 描写的使用完整的词避免 首字母缩略词和缩写词(除非 缩略语的使用更为广泛 而不是长格式,例如URL或 HTML)

秒: 尝试将代码分解为连贯的部分,并围绕您正在处理的一些常见功能组织它们。。。可能是围绕您正在编程的功能或模型

服务器的(基本)模型是它唯一做的事情是接收套接字连接。。。服务器依赖于处理程序来处理这些连接,仅此而已。如果您尝试构建该模型,它将如下所示:

class Server{
    private final ServerSocket serverSocket;
    private final ExecutorService pool;

    public Server(int port, int poolSize) throws IOException {
      serverSocket = new ServerSocket(port);
      pool = Executors.newFixedThreadPool(poolSize);
    }

    public void serve() {
      try {
        while(true) {
          pool.execute(new Handler(serverSocket.accept()));
        }
      } catch (IOException ex) {
        pool.shutdown();
      }
    }
  }

  class Handler implements Runnable {
    private final Socket socket;
    Handler(Socket socket) { this.socket = socket; }
    public void run() {
      // receive the datagram packets
    }
 }
第三:我建议您查看一些现有示例

  • 多线程客户端/服务器应用程序:
  • 道格·李:
    (感谢约翰)
    (仍然找不到确切的例子,但它就在那里的某个地方……如果你有勇气的话,看看他的档案)
  • 实践示例中的并发性:
  • Java并发教程:
根据评论更新:
好的,拉维,你的代码有一些大问题和一些小问题:

  • 我假设
    Receive
    类是您的客户机。。。您应该将其作为一个单独的程序(具有自己的主类)取出,并同时运行服务器和多个客户端。从服务器上为您发送的每个新UDP包生成一个新的“客户端线程”是一个令人不安的想法(大问题)

  • 制作客户端应用程序时,应使其在自己的
    循环中运行接收代码(小问题),例如:

  • 每个客户端只需要一个线程,每个服务器只需要一个线程(从技术上讲,这里甚至没有单独的线程,因为main有自己的线程),因此您可能觉得
    ExecutorService
    不太有用


  • 否则你的方法是正确的。。。但我仍然建议您查看一些示例。

    2个线程就可以了。一个读者一个作家。请记住,对于UDP,您不应该产生新的处理程序线程(除非您所做的工作需要很长时间),我建议将传入消息抛出到处理队列中。发送也一样,有一个发送线程阻止UDP发送的传入队列。

    Eclipse的历史记录即使在一天之前也能正常工作,这是一件好事:)多亏了这一点,我能够为Ravi和Lirik提供一个关于泄漏的工作示例和答案

    首先,让我声明,我不知道是什么导致了这次泄漏,但如果我将其保留足够长的时间,它将在出现OutOfMemoryError时失败

    其次,我留下了为Ravi注释的工作代码,作为我的UDP服务器的一个基本工作示例。超时时间是用来测试我的防火墙会杀死接收器端多长时间(30秒)。只要把游泳池里的东西移走,你就可以走了

    下面是我的示例线程化UDP服务器的一个工作但泄漏的版本

    public class TestServer {
    
    private static Integer TIMEOUT = 30;
    private final static int MAX_BUFFER_SIZE = 8192;
    private final static int MAX_LISTENER_THREADS = 5;
    private final static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss.SSSZ");
    
    private int mPort;
    private DatagramSocket mSocket;
    
    // You can remove this for a working version
    private ExecutorService mPool;
    
    public TestServer(int port) {
        mPort = port;
        try {
            mSocket = new DatagramSocket(mPort);
            mSocket.setReceiveBufferSize(MAX_BUFFER_SIZE);
            mSocket.setSendBufferSize(MAX_BUFFER_SIZE);
            mSocket.setSoTimeout(0);
    
            // You can uncomment this for a working version
            //for (int i = 0; i < MAX_LISTENER_THREADS; i++) {
            //  new Thread(new Listener(mSocket)).start();
            //}
    
            // You can remove this for a working version
            mPool = Executors.newFixedThreadPool(MAX_LISTENER_THREADS);
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // You can remove this for a working version
    public void start() {
        try {
            try {
                while (true) {
                    mPool.execute(new Listener(mSocket));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } finally {
            mPool.shutdown();
        }
    }
    
    private class Listener implements Runnable {
    
        private final DatagramSocket socket;
    
        public Listener(DatagramSocket serverSocket) {
            socket = serverSocket;
        }
    
        private String readLn(DatagramPacket packet) throws IOException {
            socket.receive(packet);
            return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(packet.getData())), MAX_BUFFER_SIZE).readLine();
        }
    
        private void writeLn(DatagramPacket packet, String string) throws IOException {
            packet.setData(string.concat("\r\n").getBytes());
            socket.send(packet);
        }
    
        @Override
        public void run() {
            DatagramPacket packet = new DatagramPacket(new byte[MAX_BUFFER_SIZE], MAX_BUFFER_SIZE);
            String s;
            while (true) {
                try {
                    packet = new DatagramPacket(new byte[MAX_BUFFER_SIZE], MAX_BUFFER_SIZE);
                    s = readLn(packet);
                    System.out.println(DateFormat.format(new Date()) + " Received: " + s);
                    Thread.sleep(TIMEOUT * 1000);
                    writeLn(packet, s);
                    System.out.println(DateFormat.format(new Date()) + " Sent: " + s);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main(String[] args) {
        if (args.length == 1) {
            try {
                TIMEOUT = Integer.parseInt(args[0]);
            } catch (Exception e) {
                TIMEOUT = 30;
            }
        }
        System.out.println(DateFormat.format(new Date()) + " Timeout: " + TIMEOUT);
        //new TestServer(4444);
        new TestServer(4444).start();
    }
    }
    
    公共类TestServer{
    私有静态整数超时=30;
    私有最终静态int MAX_BUFFER_SIZE=8192;
    私有最终静态int MAX_LISTENER_THREADS=5;
    私有最终静态SimpleDataFormat DateFormat=新SimpleDataFormat(“yyyy-dd-MM HH:MM:ss.SSSZ”);
    私人进口;
    私有DatagramSocket-mSocket;
    //您可以为工作版本删除此项
    私人服务mPool;
    公共测试服务器(int端口){
    mPort=端口;
    试一试{
    mSocket=新的DatagramSocket(mPort);
    mSocket.setReceiveBufferSize(最大缓冲区大小);
    mSocket.setSendBufferSize(最大缓冲区大小);
    mSocket.setSoTimeout(0);
    //您可以取消对工作版本的注释
    //对于(int i=0;ipublic class TestServer {
    
    private static Integer TIMEOUT = 30;
    private final static int MAX_BUFFER_SIZE = 8192;
    private final static int MAX_LISTENER_THREADS = 5;
    private final static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss.SSSZ");
    
    private int mPort;
    private DatagramSocket mSocket;
    
    // You can remove this for a working version
    private ExecutorService mPool;
    
    public TestServer(int port) {
        mPort = port;
        try {
            mSocket = new DatagramSocket(mPort);
            mSocket.setReceiveBufferSize(MAX_BUFFER_SIZE);
            mSocket.setSendBufferSize(MAX_BUFFER_SIZE);
            mSocket.setSoTimeout(0);
    
            // You can uncomment this for a working version
            //for (int i = 0; i < MAX_LISTENER_THREADS; i++) {
            //  new Thread(new Listener(mSocket)).start();
            //}
    
            // You can remove this for a working version
            mPool = Executors.newFixedThreadPool(MAX_LISTENER_THREADS);
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // You can remove this for a working version
    public void start() {
        try {
            try {
                while (true) {
                    mPool.execute(new Listener(mSocket));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } finally {
            mPool.shutdown();
        }
    }
    
    private class Listener implements Runnable {
    
        private final DatagramSocket socket;
    
        public Listener(DatagramSocket serverSocket) {
            socket = serverSocket;
        }
    
        private String readLn(DatagramPacket packet) throws IOException {
            socket.receive(packet);
            return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(packet.getData())), MAX_BUFFER_SIZE).readLine();
        }
    
        private void writeLn(DatagramPacket packet, String string) throws IOException {
            packet.setData(string.concat("\r\n").getBytes());
            socket.send(packet);
        }
    
        @Override
        public void run() {
            DatagramPacket packet = new DatagramPacket(new byte[MAX_BUFFER_SIZE], MAX_BUFFER_SIZE);
            String s;
            while (true) {
                try {
                    packet = new DatagramPacket(new byte[MAX_BUFFER_SIZE], MAX_BUFFER_SIZE);
                    s = readLn(packet);
                    System.out.println(DateFormat.format(new Date()) + " Received: " + s);
                    Thread.sleep(TIMEOUT * 1000);
                    writeLn(packet, s);
                    System.out.println(DateFormat.format(new Date()) + " Sent: " + s);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main(String[] args) {
        if (args.length == 1) {
            try {
                TIMEOUT = Integer.parseInt(args[0]);
            } catch (Exception e) {
                TIMEOUT = 30;
            }
        }
        System.out.println(DateFormat.format(new Date()) + " Timeout: " + TIMEOUT);
        //new TestServer(4444);
        new TestServer(4444).start();
    }
    }