【发布时间】:2014-09-08 12:56:15
【问题描述】:
我使用套接字作为 C 程序和 Java 程序之间的桥梁。 C 端是服务器套接字,从 Java 端接收数据,处理数据并返回结果。 Java 端是客户端套接字,将数据发送到 C 端进行处理,然后从 C 端接收结果。
C 端代码(服务器):
const int SOCKET_BUF_IN_LEN = 160024; //socket_buf_in length
const int SOCKET_BUF_OUT_LEN = 5000; //socket_buf_out length
unsigned char socket_buf_in[SOCKET_BUF_IN_LEN];
unsigned char socket_buf_out[SOCKET_BUF_OUT_LEN];
struct AlgSocketIn alg_socket_in;
struct AlgSocketOut alg_socket_out;
//... some socket connection setup code
setsockopt(new_socket_fd, SOL_SOCKET, SO_RCVBUF, &SOCKET_BUF_IN_LEN, sizeof(SOCKET_BUF_IN_LEN));
bytes_recv = recv(new_socket_fd, socket_buf_in, SOCKET_BUF_IN_LEN, 0);
run_alg(); //process the data
bytes_send = send(new_socket_fd, socket_buf_out, SOCKET_BUF_OUT_LEN, 0);
如上所述,套接字发送缓冲区socket_buf_in 有 160024 个字节。我使用setsockopt() 将套接字缓冲区设置为这个大小。
Java 端代码(客户端):
public AlgOutData sendRecvData(AlgInData inData, int portNum) {
AlgOutData outData = new AlgOutData();
Socket sock = new Socket("localhost", portNum);
int sentBytes, recvBytes;
sock.setSendBufferSize(160024);
sentBytes = serializeData(inData, sock); //send data to server
recvBytes = deserializeData(outData, sock); //receive result from server
sock.close();
return outData;
}
private int serializeData(AlgInData inData, Socket socket) throws IOException {
int totalNumSamples = 160024;
DataOutputStream os = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), 160024));
for(int i=0; i<totalNumSamples; i++) {
os.writeByte(inData.getSamples()[i]);
}
os.flush();
int numBytes = os.size();
return numBytes;
}
但是当我同时启动 C 程序和 Java 程序并完成从 Java 端向 C 端发送字节时,我发现 C 端只从 TCP 套接字流中接收到 65536 个字节。我调试它并通过查看 C 代码中的这一行发现了这一点:
bytes_recv = recv(new_socket_fd, socket_buf_in, SOCKET_BUF_IN_LEN, 0);
完成此调用后,bytes_recv 是 65536 字节,而不是 160024 字节,这是 socket_buf_in 的长度。
但是在Java端,我发现发送的数据确实是160024字节。在serializeData(),行显示
//....
os.flush();
int numBytes = os.size();
numBytes 是调用os.flush() 后的 160024。
那么为什么我在 C 端只得到 65536 字节的数据,而 Java 端发送所有 160024 字节的数据呢?我是否在 C 端正确使用了正确的套接字发送/接收功能?
我也尝试在 C 端使用以下代码重复接收字节流,直到接收到所有 160024 个字节:
num_bytes = 0;
while (num_bytes < SOCKET_BUF_IN_LEN) {
bytes_recv = recv(new_socket_fd, socket_buf_in, SOCKET_BUF_IN_LEN, 0);
if (bytes_recv < 0)
handle_error("Error on socket recv.\n");
num_bytes += bytes_recv;
}
但这一次,即使num_bytes 是160024,套接字缓冲区socket_buf_in[160024] 的值全为零,这是错误的。
另一方面,当我调试 Java 端代码时,我发现即使我将输出流对象 os 设置为 160024 缓冲区大小,它也只能正确写入最多 20024 字节的字节,而不是 160024 字节。
对于 160024 字节的套接字通信,C 端或 Java 端代码有什么问题?
【问题讨论】: