为什么在C和Java代码之间的套接字通信中只接收64K数据?

时间:2014-07-17 15:04:23

标签: java c sockets tcp

我使用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端代码有什么问题?

1 个答案:

答案 0 :(得分:1)

你的最终循环看起来几乎是正确的,但是当你将数据读入数组时,你需要将指针传递给recv。否则每次调用都会覆盖数组的开头。像

这样的东西
bytes_recv = recv(new_socket_fd, socket_buf_in+num_bytes, SOCKET_BUF_IN_LEN, 0);