我使用socket作为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字节。
1600字节的套接字通信的C端或Java端代码有什么问题?
答案 0 :(得分:1)
你的最终循环看起来几乎是正确的,但是当你将数据读入数组时,你需要将指针传递给recv。否则每次调用都会覆盖数组的开头。像
这样的东西bytes_recv = recv(new_socket_fd, socket_buf_in+num_bytes, SOCKET_BUF_IN_LEN, 0);