【问题标题】:Receive timed out in Java UDP socket client for Memcached在 Memcached 的 Java UDP 套接字客户端中接收超时
【发布时间】:2017-09-23 16:40:52
【问题描述】:

我有一个本地 Memcached 实例并尝试通过基本的 Java TCP 和 UDP 套接字 API 访问它。 TCP 客户端工作正常,但 UDP 客户端总是抛出异常。

java.net.SocketTimeoutException: Receive timed out
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
    at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:144)
    at java.net.DatagramSocket.receive(DatagramSocket.java:812)
    at test.Test.udp(Test.java:71)
    at test.Test.main(Test.java:10)

无论我设置什么超时。

这是我正在运行的代码。我是套接字编程的新手请帮助找出问题。

import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;

public class Test {
    public static void main(String [] args) {
        //tcp();
        udp();
    }

    private static void tcp(){
        String serverName = "127.0.0.1";
        int port = 11211;
        try {
            System.out.println("Connecting to " + serverName + " on port " + port);
            Socket client = new Socket(serverName, port);

            System.out.println("Just connected to " + client.getRemoteSocketAddress());
            OutputStream outToServer = client.getOutputStream();
            DataOutputStream out = new DataOutputStream(outToServer);

            out.writeBytes("stats\r\n");
            InputStream inFromServer = client.getInputStream();
            DataInputStream in = new DataInputStream(inFromServer);

            System.out.println("Server says " + in.readLine());

            client.close();
        }catch(IOException e) {
            e.printStackTrace();
        }
    }

    private static void udp(){
        DatagramSocket socket = null ;

        try
        {
            InetAddress host = InetAddress.getByName("localhost") ;
            socket = new DatagramSocket() ;
            byte [] data = "stats\r\n".getBytes() ;
            DatagramPacket packet = new DatagramPacket( data, data.length, host, 11211 ) ;
            socket.send( packet ) ;
            socket.setSoTimeout( 2000 ) ;
            packet.setData( new byte[1024] ) ;
            socket.receive( packet ) ;
            System.out.println( new String(packet.getData()) ) ;

        }
        catch( Exception e )
        {
            System.out.println( e ) ;
        }
        finally
        {
            if( socket != null )
                socket.close() ;
        }
    }

}

【问题讨论】:

  • 您可以尝试捕获超时异常并循环尝试再次接收。
  • @SteveSmith 我在循环中尝试了 100 次重试仍然没有运气。
  • 服务器是否真的在发送响应?
  • 我使用以下命令检查服务器是否正在侦听 UDP。 sbm@LISP:~$nc -v -u -z -w 3 127.0.0.1 11211-11211 连接到 127.0.0.1 11211 端口 [udp/*] 成功!如果有更好的方法来检查服务器是否实际发送响应,请让我看看

标签: java sockets networking udp memcached


【解决方案1】:

根据 memcached 文档 (https://github.com/memcached/memcached/blob/master/doc/protocol.txt) ,使用 udp 协议发送数据时,应发送 8 字节的标头,后跟 与 TCP 协议的格式相同。头部结构如下:

  • 0-1 请求 ID
  • 2-3 序号
  • 4-5 此消息中的数据报总数
  • 6-7 保留供将来使用;必须是 0

在发送数据时添加头字节。像这样的:

    try
    {
        InetAddress host = InetAddress.getByName("localhost") ;
        socket = new DatagramSocket() ;

        byte [] data = "stats\r\n".getBytes() ;
        ByteBuffer buffer = ByteBuffer.allocate(50);
        buffer.putShort((short)0);
        buffer.putShort((short) 0x0000;);
        buffer.putShort((short) 0x0001;);
        buffer.putShort((short) 0x0000;);
        buffer.put(data);
        DatagramPacket packet = new DatagramPacket( buffer.array(), buffer.array().length, host, 11211 ) ;
        socket.send( packet) ;
        socket.setSoTimeout( 2000 ) ;
        packet.setData( new byte[1024] ) ;
        socket.receive( packet ) ;
        System.out.println( new String(packet.getData()) ) ;

    }
    catch( Exception e )
    {
       e.printStackTrace();
    }
    finally
    {
        if( socket != null )
            socket.close() ;
    }

【讨论】:

    猜你喜欢
    • 2016-05-09
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 2011-07-31
    • 2017-06-01
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    相关资源
    最近更新 更多