【问题标题】:Receiving data from server to client从服务器接收数据到客户端
【发布时间】:2014-06-19 05:49:18
【问题描述】:

我有这三个类,TCPClient、TCPServer 和 Member。我正在使用 TCPClient 将 RequestPacket 对象发送到 TCPServer,然后 TCPServer 以字符串响应 TCPClient。代码如下:

TCP服务器

import java.io.*;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.io.ObjectInputStream.GetField;
import java.net.*;

import data.RequestPacket;
public class TCPServer {
private static LinkedHashMap<Integer,String> port_database_map = new LinkedHashMap();
static{
    port_database_map.put(2131,"testing1");
    port_database_map.put(6789, "testing2");

}
public static void main(String[] args) throws Exception {
    if(args.length==1){
    String clientSentence;
    String capitalizedSentence;
    new TCPServer().sqlConnectionTest();

    ServerSocket welcomeSocket = new ServerSocket(Integer.parseInt(args[0]));

    System.out.println("Server running at "+welcomeSocket.getLocalSocketAddress()+" and port "+welcomeSocket.getLocalPort());
    Socket connectionSocket = welcomeSocket.accept();
    InputStream is = connectionSocket.getInputStream();
    ObjectInputStream ois = new ObjectInputStream(is);
    DataOutputStream outToClient;
    //DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
    while(true){

    //  BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));

        outToClient = new DataOutputStream(connectionSocket.getOutputStream());
        //clientSentence = inFromClient.readLine();
        RequestPacket rp = (RequestPacket) ois.readObject();
        outToClient.writeUTF(rp.query);
        outToClient.flush();
        System.out.println("Received object "+rp.query);
        //System.out.println("Client sentence is "+clientSentence);
        //capitalizedSentence = getClientResponse(clientSentence);
    //  outToClient.writeBytes(getClientResponse(clientSentence));


    }
    } else{
        System.out.println("Enter port numnber as argument");
        System.exit(1);
    }
}

public static String getClientResponse(String clientRequest){

    return clientRequest.toUpperCase().trim()+'\n';
}

public void sqlConnectionTest(){
    String sqlString;
    try{
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("MySQLJDBC Driver registered");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:8889/testing1","root","root");
        if(connection!=null){
            System.out.println("You made it!");

        }else
            System.out.println("Connection failed");
    }catch(ClassNotFoundException e){
        System.out.println("Where is your mySQL JDBC Driver? "+e);

    }catch(SQLException e){
        System.out.println("Caught SQLException "+e);
    }
}
}

TCPClient

import java.io.*;
import java.net.*;
import java.util.Scanner;

import data.RequestPacket;
import data.RequestPacket.RequestType;
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
    if(args.length==1){
    String sentence;
    String modifiedSentence;

    //BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
    Socket clientSocket = new Socket("0.0.0.0",Integer.parseInt(args[0]));
    String query = "SELECT * FROM NOTHING";
    //Scanner in = new Scanner(System.in);
    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
    RequestPacket rp = new RequestPacket(Integer.parseInt(args[0]), query, RequestType.NEW_REGISTRATION);
    OutputStream os = clientSocket.getOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(os);
    /*while(in.hasNextLine())*/if(rp.port!=0){
        DataInputStream inFromServer = new DataInputStream(clientSocket.getInputStream());
        //sentence = in.nextLine();

        //sentence = "Hello, this is Rohan";
        System.out.println("Sentence is "+rp);
        oos.writeObject(rp);
        //outToServer.writeUTF(rp+"\n");
        //outToServer.writeBytes(sentence+"\n");
        oos.flush();
        modifiedSentence = inFromServer.readLine();
        System.out.println("DONE");
        System.out.println("FROM SERVER: "+modifiedSentence);

        //outToServer.flush();
    }
    oos.close();
    os.close();
    clientSocket.close();
}else{
    System.out.println("Enter port for client to connect to");
    System.exit(1);
}
}
}

请求包 /* */ 打包数据;

import java.io.Serializable;

/**
 * @author rohandalvi
 *
 */
public class RequestPacket implements Serializable {
    public int port;
    public String query;
    public RequestType type;
    public enum  RequestType{
        NEW_REGISTRATION,IN_TRANSIT_SCAN,REPLICATION,DELETE_MEMBERSHIP,REMOVE_BENEFICIARY
    }

    public RequestPacket(int port, String query,RequestType type){
        this.port = port;
        this.query = query;
        this.type = type;
    }

}

当我运行客户端时,它会将 RequestPacket 对象发送到 TCP 服务器,但是由于某种原因,TCPServer 没有向客户端返回 rp.query 值。它这样做了,只有当我停止服务器时,我才会立即看到在客户端打印的服务器响应。

如果您知道出了什么问题,请帮忙。谢谢。

【问题讨论】:

  • 你有一个适用于客户端到服务器方向的合理的应用层协议,Java 的对象流协议。但我没有看到任何相反方向的应用层协议。那么客户端如何知道何时应该处理数据呢? (当然,当你停止服务器时除外。) TCP 101——你必须在 TCP 之上实现一个协议——它不会靠魔法工作。
  • 您有很多注释掉的代码以及与问题无关的其他代码并没有帮助。还缺少代码,例如RequestPacket。请尝试将您的代码缩减为一个简短但完整的程序,该程序可以演示问题但没有其他内容。
  • rp.query 是否在您的服务器端成功打印?
  • 您是否尝试为查询属性添加吸气剂?我在 RPC 客户端中体验过。

标签: java tcpclient tcpserver


【解决方案1】:

不要将InputStream 传递给BufferedReader,而是直接将其引用到DataInputStream 并从那里读取UTF。

样本:

      DataInputStream inFromServer = new DataInputStream(clientSocket.getInputStream());
      modifiedSentence = inFromServer.readUTF();

【讨论】:

  • 没有帮助。我更新了上面的代码以反映我所做的更改。
  • 在 java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2601) 在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1319) 的线程“主”java.io.EOFException 中的异常) 在 java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) 在 TCPServer.main(TCPServer.java:38)
  • @RohanDalvi 您处于服务器内部的一个while循环中,因此当客户端退出时,服务器仍在读取已经关闭的客户端的响应
  • @RohanDalvi 在客户端打印了吗?
  • 不,它没有在客户端打印。它是在服务器端完成的
【解决方案2】:

只要遵循来自 cmets 的 Jon Skeet 的建议(将代码缩减为一个简短但完整的程序)并使用answer from Rod_Algonquin,我就可以得到一个没有问题的程序。添加更多代码并在每次更改后继续测试,以查看程序何时中断,以便您找到给您带来麻烦的代码。

public class NetworkObjectString {

public static void main(String[] args) {

    Socket s = null;
    try {
        new Thread(new TcpServer()).start();
        // Wait for socket server to start
        Thread.sleep(500);
        // TcpClient
        s = new Socket(InetAddress.getLocalHost(), 54321);
        RequestPacket rp = new RequestPacket();
        rp.port = 123;
        rp.query = "dummy query";
        ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
        oos.writeObject(rp);
        oos.flush();
        System.out.println("Client send rp.query: " + rp.query);
        DataInputStream dis = new DataInputStream(s.getInputStream());
        String sq = dis.readUTF();
        System.out.println("Client received query: " + sq);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try { s.close(); } catch (Exception ignored) {}
    }
}

static class TcpServer implements Runnable {

    public void run() {

        ServerSocket ss = null;
        Socket s = null;
        try {
            s = (ss = new ServerSocket(54321)).accept();
            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
            RequestPacket rp = (RequestPacket) ois.readObject();
            System.out.println("Server received rp: " + rp);
            String sq = rp.query + " from server";
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            dos.writeUTF(sq);
            dos.flush();
            System.out.println("Server send query: " + sq);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try { ss.close(); } catch (Exception ignored) {}
            try { s.close(); } catch (Exception ignored) {}
        }
    }
} // TcpServer

static class RequestPacket implements Serializable {

    private static final long serialVersionUID = 1082443947105396312L;

    public String query;
    public int port;

    public String toString() { return port + " - " + query; }
}

}

【讨论】:

  • 我得到 EOFException 与此代码。我认为这是因为 readUTF()
  • @RohanDalvi 我无法重现。异常发生在哪一行?
  • EOF 异常 java.io.EOFException 在 java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2601) 在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1319) 在 java。 io.ObjectInputStream.readObject(ObjectInputStream.java:371) 在 TCPServer.main(TCPServer.java:38) RequestPacket rp = (RequestPacket) ois.readObject();
  • @RohanDalvi 所以这是服务器第一次尝试从连接中读取数据,但由于某种原因连接已经关闭(在客户端)。你看到输出Client send rp.query ...了吗?如果你是循环写/读,请检查this question中的答案和cmets。
猜你喜欢
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 1970-01-01
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
相关资源
最近更新 更多