使用客户端Java套接字同步服务器

时间:2014-02-18 10:50:25

标签: java sockets

目前我正在开发一个服务器/客户端应用程序,它使用带有Runnable线程的java发送数据。问题是客户端正在发送数据,当服务器开始读取数据时,客户端已经完成并关闭了连接,在服务器端只有部分数据到达,它们是否可以设置为同步?

这是客户端

private void ConnectionToServer(final String ipAddress, final int Port) {
   final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

   Runnable serverTask = new Runnable() {
        @Override
        public void run() {
            try {
                socket = new Socket(ipAddress, Port);

                bos = new BufferedOutputStream(socket.getOutputStream());
                dos = new DataOutputStream(socket.getOutputStream());

                File f = new File("C:/Users/lukeLaptop/Downloads/RemoveWAT22.zip");

                String data = f.getName()+f.length();
                byte[] b = data.getBytes();

                sendBytes(b, 0, b.length);


                dos.flush();
                bos.flush();

                bis.close();

                dos.close();

                //clientProcessingPool.submit(new ServerTask(socket));
           } catch (IOException ex) {
               Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);           } finally {

           }

       }
    };

    Thread serverThread = new Thread(serverTask);
    serverThread.start();

    public void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
    if (len < 0) {
        throw new IllegalArgumentException("Negative length not allowed");
    }
    if (start < 0 || start >= myByteArray.length) {
        throw new IndexOutOfBoundsException("Out of bounds: " + start);
    }
// Other checks if needed.

// May be better to save the streams in the support class;
    // just like the socket variable.
    OutputStream out = socket.getOutputStream();
    DataOutputStream dos = new DataOutputStream(out);

    dos.writeInt(len);
    if (len > 0) {
        dos.write(myByteArray, start, len);
    }
}

服务器代码

   private void acceptConnection() {

    try {

        final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);

        Runnable serverTask = new Runnable() {
            @Override
            public void run() {
                try {
                    ServerSocket server = new ServerSocket(8080);

                    while (true) {
                        socket = server.accept();

                        System.out.println("Got a client !");

                        bis = new BufferedInputStream(socket.getInputStream());

                        dis = new DataInputStream(socket.getInputStream());

                        String data = readBytes().toString();

                        System.out.println(data);


                        bos.close();

                        dis.close();

                        //clientProcessingPool.submit(new ClientTask(socket));
                    }
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        };
        Thread serverThread = new Thread(serverTask);
        serverThread.start();

    } catch (Exception io) {

        io.printStackTrace();

    }

}

public byte[] readBytes() throws IOException {
    // Again, probably better to store these objects references in the support class
    InputStream in = socket.getInputStream();
    DataInputStream dis = new DataInputStream(in);

    int len = dis.readInt();
    byte[] data = new byte[len];
    if (len > 0) {
        dis.readFully(data);
    }
    return data;
}

1 个答案:

答案 0 :(得分:7)

你混淆了很多东西:

  1. 变量大部分时间以小写字母开头,例如int port,int ipAddress
  2. 类以大写字母开头,例如客户端,服务器
  3. 仅在套接字上打开一个Data *流。 new DataInputStream(socket.getInputStream())新的BufferedInputStream(socket.getInputStream()),但不是两者
  4. 如果你需要两者,请将它们链接起来:new DataInputStream(new BufferedInputStream(socket.getInputStream()));
  5. KISS(保持简短和简单)
  6. 如果您使用DataInputStream,则使用发送对象和基元的给定功能,例如sendUTF(),sendInt(),sendShort()等......
  7. 正确命名你的vars:servertask是一个客户端线程?无
  8. 将长匿名类移至新类
  9. 不要使用端口8080,此端口用于许多其他应用程序并会导致问题
  10. 关于您的示例的示例代码和我的建议:

    服务器

    public class Server implements Runnable {
        private void acceptConnection() {
                Thread serverThread = new Thread(this);
                serverThread.start();
        }
    
        @Override
        public void run() {
            try {
                ServerSocket server = new ServerSocket(8081);
    
                while (true) {
                    Socket socket = server.accept();
                    System.out.println("Got a client !");
    
                    // either open the datainputstream directly
                    DataInputStream dis = new DataInputStream(socket.getInputStream());
                    // or chain them, but do not open two different streams:
                    // DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    
                    // Your DataStream allows you to read/write objects, use it!
                    String data = dis.readUTF();
                    System.out.println(data);
    
                    dis.close();
                    // in case you have a bufferedInputStream inside of Datainputstream:
                    // you do not have to close the bufferedstream
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new Server().acceptConnection();
        }
    }
    

    描述:

    1. main:创建一个新的服务器对象,它是一个Runnable
    2. acceptConnections:创建一个主题
    3. 运行:
      1. 打开Serversocket
      2. 等待连接
      3. 只打开一个流
      4. 阅读数据
      5. 关闭流并等待下一次连接
    4. <强>客户端

      public class Client {
          private static void sendToServer(String ipAddress, int port) throws UnknownHostException, IOException {
              Socket socket = new Socket(ipAddress, port);
      
              // same here, only open one stream
              DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
      
              File f = new File("C:/Users/lukeLaptop/Downloads/RemoveWAT22.zip");
              String data = f.getName()+f.length();
      
              dos.writeUTF(data);
      
              dos.flush();
              dos.close();    
          }
      
          public static void main(String[] args) throws UnknownHostException, IOException {
              Client.sendToServer("localhost", 8081);
          }
      }
      

      描述(这是直截了当的):

      1. 打开套接字
      2. 打开DataStream
      3. 发送数据
      4. 刷新并关闭