套接字数据似乎没有通过客户端

时间:2012-06-22 09:59:20

标签: java sockets

我已经写了一些服务器端套接字处理代码,我担心可能我的数据包并不总是回到客户端。我正在记录我的所有事件,并在我的日志文件中说它我正在发送信息。但是客户端也记录了事件,他们说他们没有收到任何东西。

我发送数据的代码如下:

public void write(Packet packet) {
    String data = packet.serialize();
    log("Send=[" + data + "]", "Write"); // log to file

    try {
        _writer.write(data);
        _writer.flush();
    } catch (Exception ex) {
        log(ex, "write");
    }
}

每个套接字都是在一个新线程上创建的,我会立即创建我的作者和读者(在公共运行方法中):

// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
                    .getOutputStream()));
            _reader = new SocketReader(_socket);

SocketReader只是我为侦听响应而创建的包装类,并且有一个像这样的公共读取方法:

public String read() throws IOException, SocketTimeoutException {

    _socket.setSoTimeout(_timeOut);

    if(_reader == null)
        _reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));

            // read from the stream
    return new PacketDataInputStream(_reader).read();
}

PacketDataInputStream包装类:

BufferedReader _reader = null;

public PacketDataInputStream(BufferedReader reader)
{
    _reader = reader;
}

public String read() throws IOException, SocketException {

    StringBuilder builder = new StringBuilder();
    int c = 0;

    while((c = _reader.read()) != -1)
    {
        char ch = (char)c;

        builder.append(ch);

        if(ch == PacketConstants.ETX)
            break;
    }

    if(builder.length() > 0)
        return builder.toString();
    else
        return null;

}

我认为创建实际套接字侦听器对象的方式非常标准:

InetAddress address = InetAddress.getByName(IP);
        server = new ServerSocket( port, 0, address);

                    // My own manager class to handle all the sockets connected 
        WebSocketManager manager = new WebSocketManager(this);

        Socket connection = null;

        while(bContinue)
        {
            connection = server.accept();

            if(bContinue) {
                                    // assign the socket to a new thread and start
                                    // that thread
                manager.newSocket(connection);  
            } else {
                connection.close();
            }
        }
  • 我可能正在使用错误的对象来发回数据。
  • 我是否应该使用缓冲区和阅读器?我原以为这是最好的方式,但现在我不太确定。

重要的是要注意,这不会偶尔发生,只是偶尔发生。它可能是客户端代码有错误,但我需要确保我在回到它们之前正确地执行它。

此代码在 Linux Ubuntu 服务器上运行。记录发生在文本文件中,没有什么特别之处。我的日志文件显示发送=“”数据返回到客户端并且没有异常,因此看起来好像.write和.flush()有效吗?套接字连接是持久的,只能由客户端和/或网络问题关闭。

更新-----客户端代码-------:

我确实设法获得了一些客户端代码,以了解他们如何处理数据的发送和接收(以防万一在他们的结尾更明显)。客户端实际上是通过 Android设备连接到此服务器(如果有帮助的话)。

创建套接字

static final int BUFFER_SIZE = 20000;       // Maximum packet size

java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);

发送:

try {
            // Send the packet:
        OutputStream stream = socket.getOutputStream();
        stream.write(p.getByteArray ());
        stream.flush();

            // Update the time:
        lastPacketSendTime = new Date ();
    } catch (IOException e) {
        setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
        return false;
    }

接收:

socket.setSoTimeout(timeout);
            // Get the reader:
        inputStream = socket.getInputStream();



     while (true) {
                    // Get the next character:
                int value = inputStream.read();
                    // Check for -1, indicating that the socket is closed:
                if (value == -1) {
                        // The socket is closed remotely, so close it locally as well:
                    disconnect();
                    inputStream = null;
                    return null;
                }
                                // ... and a bunch of other stuff to handle the actual data

                        }

编辑11月14日: 实际上,这实际上证明是一个问题。客户端日志和服务器日志似乎都在发送。但有时数据似乎没有通过,或者如果有的话,有时会延迟10 - 30 - 60秒。

如果需要,我可以提供更多信息。

2 个答案:

答案 0 :(得分:1)

当您使用BufferedReaders和BufferedWriters时,事情会被缓冲。如何直接使用输入和输出流..此外,编写器是基于字符的,我不知道你是否需要发送二进制数据,但如果是这样,这将是编写者的问题。

答案 1 :(得分:0)

我不确定这是否适合您使用..但我给你的是用于客户端服务器通信的代码..

客户端:

public class ClientWala {

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

        Boolean b = true;
    Socket s = new Socket("127.0.0.1", 4444);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}

服务器代码:

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


public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}
相关问题