通过Java Socket发送二进制文件

时间:2016-06-16 01:11:32

标签: java sqlite sockets tcp

我编写了一个多客户端TCP服务器,它具有发送Json(基于文本)命令字符串以及向多个客户端发送SQLite数据库文件的双重目的。一切都很好,除了...数据库文件使用特殊字符hex81(十进制129)用于某些内部目的。当我将数据库文件读入字节数组时,由于Java的带符号字节表示,Java会将此字符转换为十进制-127。但是套接字实际上是将此字符作为hex3F传输。因此,当我收到客户端中的数据保存并将其保存到文件时,由于存在h3F字符而不是h81,数据库已损坏。

为什么会发生这种情况,我该如何纠正?

以下是我用于服务器的完整代码(无论何时客户端连接,此类的新实例都由单独的TCPServer类启动):

{{1}}

}

1 个答案:

答案 0 :(得分:-1)

正如EJP建议的那样,问题在于使用读者和作者。 以下代码现在按预期工作(感谢提示EJP)。我将解决VGR引发的关于在PrintWriter和BufferedOutputStream中包装client.getOutputStream()的问题,但是现在代码运行良好(这是一项正在进行的工作)。

public class TCPServerThread extends Thread {

// Connect status constants
private final static int NULL = 0;
private final static int DISCONNECTED = 1;
private final static int DISCONNECTING = 2;
private final static int BEGIN_CONNECT = 3;
private final static int CONNECTED = 4;

private final static String END_SESSION = new Character((char)0).toString(); // Indicates the end of a session

// Connection state info
private int connectionStatus = DISCONNECTED;

private static StringBuffer txBuffer = new StringBuffer("");
private static BufferedOutputStream out2 = null; 

private static File file;

// TCP Components
private ServerSocket serverSocket = null;
private Socket clientSocket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private static BufferedInputStream fileData = null;
private String s = "";

private DecodeJson dj = new DecodeJson();
private boolean doRun;  


public TCPServerThread(Socket socket) throws IOException {

    doRun = true;
    clientSocket = socket;      
    changeStatusTS(BEGIN_CONNECT, true);

}

public void run() {

    while (doRun) {
        try { // run every ~10 ms
            Thread.sleep(10);
        }
        catch (InterruptedException e) {}

        if (Mainscreen.shutdown == true || TCPClient.close == true) 
            connectionStatus = DISCONNECTING;

        switch (connectionStatus) {

            case BEGIN_CONNECT:

                try {
                    in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                    out = new PrintWriter(clientSocket.getOutputStream(), true);
                    out2 = new BufferedOutputStream(clientSocket.getOutputStream());

                    TCPServer.writers.add(out);             // add this socket to the connected clients list
                    changeStatusTS(CONNECTED, true);
                }
                // If error, clean up and output an error message
                catch (IOException e) {
                    cleanUp();
                    changeStatusTS(DISCONNECTED, false);
                }
                break;

            case CONNECTED:

                try {
                    // Send data
                    if (txBuffer.length() != 0) {
                        for (PrintWriter writer : TCPServer.writers) {
                            writer.print(txBuffer);
                            writer.flush();

                            if(writer.checkError()) {
                            closeSocket();
                            changeStatusTS(DISCONNECTING, true);

                            }else {
                                changeStatusTS(NULL, true);
                            }
                        }
                        txBuffer.setLength(0);
                    }

                    if (fileData != null) {
                        byte[] buffer = new byte[(int) file.length()];
                        for (int read = fileData.read(buffer); read >=0; read = fileData.read(buffer)) out2.write(buffer, 0, read);
                        out2.flush();
                        fileData = null;
                    }

                    // Receive data
                    if (in.ready()) {
                        s = in.readLine();
                        if ((s != null) &&  (s.length() != 0)) {
                            // Check if it is the end of a transmission
                            if (s.equals(END_SESSION)) {
                                changeStatusTS(DISCONNECTING, true);
                            }
                            // Otherwise, receive text
                            else {                                  
                                dj.receiveString(s);
                                changeStatusTS(NULL, true);
                            }
                        }
                    }
                }
                catch (IOException e) {
                    System.out.println("Socket error " + e);
                    cleanUp();
                    changeStatusTS(DISCONNECTED, false);
                }
                break;

            case DISCONNECTING:

                // Tell clients to disconnect as well
                if (out != null) {
                    out.print(END_SESSION);
                    out.flush();
                }
                // Clean up (close all streams/sockets)
                cleanUp();
                changeStatusTS(DISCONNECTED, true);
                break;

            default: break;
        }
    }
}

// Add command to text send-buffer
public static void sendString(String s) {

    synchronized (txBuffer) {
        txBuffer.append(s + "\n");
    }
}

// Add file data to binary send buffer
public static void sendFile(String filename) {

    file = new File(filename);                      
    try {
        fileData = new BufferedInputStream(new FileInputStream(file));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

}

private void changeStatusTS(int newConnectStatus, boolean noError) {

    // Change state if valid state
    if (newConnectStatus != NULL) {
        connectionStatus = newConnectStatus;
    }

}

private void closeSocket(){
    try {
        if (clientSocket != null) {
            clientSocket.close();
            clientSocket = null;
        }
    }
    catch (IOException e) { clientSocket = null; }   

}

// Cleanup for disconnect
private void cleanUp() {
    try {
        if (serverSocket != null) {
            serverSocket.close();
           serverSocket = null;
        }
    }
    catch (IOException e) { serverSocket = null; }

    try {
        if (clientSocket != null) {
            clientSocket.close();
            clientSocket = null;
        }
    }
    catch (IOException e) { clientSocket = null; }

    try {
        if (in != null) {
            in.close();
           in = null;
        }
    }
    catch (IOException e) { in = null; }

    if (out != null) {
        TCPServer.writers.remove(out);          // remove this socket for the connected sockets list
        out.close();
        out = null;
    }
    doRun = false;

}

}