4

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

我发送数据的代码如下:

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服务器上运行。记录发生在一个文本文件中,没有什么特别的。我的日志文件显示Send=""数据返回客户端并且没有异常,因此看起来好像 .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 秒。

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

4

2 回答 2

1

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

客户端:

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();

    }

}
于 2012-06-22T20:08:21.127 回答
1

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

于 2012-06-22T19:49:07.737 回答