简体   繁体   English

如何使用相同的套接字发送二进制文件和文本

[英]how to send both binary file and text using the same socket

i have to send a short string as text from client to server and then after that send a binary file. 我必须将一个短字符串作为文本从客户端发送到服务器,然后发送一个二进制文件。

how would I send both binary file and the string using the same socket connection? 如何使用相同的套接字连接发送二进制文件和字符串?

the server is a java desktop application and the client is an Android tablet. 服务器是一个Java桌面应用程序,客户端是Android平板电脑。 i have already set it up to send text messages between the client and server in both directions. 我已经将其设置为在两个方向上在客户端和服务器之间发送文本消息。 i have not yet done the binary file sending part. 我还没有完成二进制文件发送部分。

one idea is to set up two separate servers running at the same time. 一个想法是设置两个单独的服务器同时运行。 I think this is possible if i use two different port numbers and set up the servers on two different threads in the application. 我认为如果我使用两个不同的端口号并在应用程序中的两个不同线程上设置服务器,这是可能的。 and i would have to set up two concurrent clients running on two services in the Android app. 我将不得不设置在Android应用程序中的两个服务上运行的两个并发客户端。

the other idea is to somehow use an if else statement to determine which of the two types of files is being sent, either text of binary, and use the appropriate method to receive the file for the file type being sent. 另一个想法是以某种方式使用if else语句来确定发送两种类型文件中的哪一种(二进制文本),并使用适当的方法接收正在发送的文件类型的文件。

example code for sending text 发送文本的示例代码

 PrintWriter out;
 BufferedReader in;

out = new PrintWriter(new BufferedWriter
(new OutputStreamWriter(Socket.getOutputStream())) true,);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

out.println("test out");
String message = in.readLine();

example code for sending binary file 发送二进制文件的示例代码

 BufferedOutputStream out;
 BufferedInputStream in;
 byte[] buffer = new byte[];
 int length = 0;

 out = new BufferedOutputStream(new FileOutputStream("test.pdf));
 in = new BufferedInputStream(new FileOutputStream("replacement.pdf"));

 while((length = in.read(buffer)) > 0 ){
 out.write(buffer, 0, length);
 }

I don't think using two threads would be necessary in your case. 我不认为在你的情况下使用两个线程是必要的。 Simply use the socket 's InputStream and OutputStream in order to send binary data after you have sent your text messages. 只需使用socketInputStreamOutputStream ,就可以在发送短信后发送二进制数据。

Server Code 服务器代码

OutputStream stream = socket.getOutputStream();
PrintWriter out = new PrintWriter(
    new BufferedWriter(
        new OutputStreamWriter(stream)
    )
);
out.println("test output");
out.flush(); // ensure that the string is not buffered by the BufferedWriter

byte[] data = getBinaryDataSomehow();
stream.write(data);

Client Code 客户代码

InputStream stream = socket.getInputStream();
String message = readLineFrom(stream);

int dataSize = getSizeOfBinaryDataSomehow();
int totalBytesRead = 0;
byte[] data = new byte[dataSize];

while (totalBytesRead < dataSize) {
    int bytesRemaining = dataSize - totalBytesRead;
    int bytesRead = stream.read(data, totalBytesRead, bytesRemaining);

    if (bytesRead == -1) {
        return; // socket has been closed
    }

    totalBytesRead += bytesRead;
}

In order to determine the correct dataSize on the client side you have to transmit the size of the binary block somehow. 为了在客户端确定正确的dataSize ,您必须以某种方式传输二进制块的大小。 You could send it as a String right before out.flush() in the Server Code or make it part of your binary data. 您可以在服务器代码中的out.flush()之前将其作为字符串发送,或者将其作为二进制数据的一部分。 In the latter case the first four or eight bytes could hold the actual length of the binary data in bytes. 在后一种情况下,前四个或八个字节可以保持二进制数据的实际长度(以字节为单位)。

Hope this helps. 希望这可以帮助。


Edit 编辑

As @EJP correctly pointed out, using a BufferedReader on the client side will probably result in corrupted or missing binary data because the BufferedReader "steals" some bytes from the binary data to fill its buffer. 正如@EJP正确指出的那样,在客户端使用BufferedReader可能会导致二进制数据损坏或丢失,因为BufferedReader “窃取”二进制数据中的一些字节以填充其缓冲区。 Instead you should read the string data yourself and either look for a delimiter or have the length of the string data transmitted by some other means. 相反,您应该自己读取字符串数据,并查找分隔符或通过其他方式传输字符串数据的长度。

/* Reads all bytes from the specified stream until it finds a line feed character (\n).
 * For simplicity's sake I'm reading one character at a time.
 * It might be better to use a PushbackInputStream, read more bytes at
 * once, and push the surplus bytes back into the stream...
 */
private static String readLineFrom(InputStream stream) throws IOException {
    InputStreamReader reader = new InputStreamReader(stream);
    StringBuffer buffer = new StringBuffer();

    for (int character = reader.read(); character != -1; character = reader.read()) {
        if (character == '\n')
            break;
        buffer.append((char)character);
    }

    return buffer.toString();
}

You can read about how HTTP protocol works which essentially sends 'ascii and human readable' headers (so to speak) and after that any content can be added with appropriate encoding like base64 for example. 您可以阅读HTTP协议如何工作,它基本上发送'ascii和人类可读'标题(可以这么说),然后可以使用适当的编码添加任何内容,例如base64。 You may create sth similar yourself. 您可以自己创建类似的东西。

您需要首先发送String,然后发送字节数组的大小,然后发送字节数组,使用String.startsWith()方法检查发送的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM