通过套接字从Java向C发送int-奇怪的结果

通过套接字从Java向C发送int-奇怪的结果,java,c,sockets,network-programming,Java,C,Sockets,Network Programming,我有一个用Java编写的简单服务器,它只向连接的客户机发送一个整数。我有一个用C编写的客户端,它连接到服务器并打印出接收到的整数 我的问题是结果各不相同。执行客户机时,大约有一半的时间我得到了正确的结果(234),但其他时间我得到了8323072 这是服务器: class TCPServer { public static void main(String args[]) throws Exception { ServerSocket welcomeSocket = new Ser

我有一个用Java编写的简单服务器,它只向连接的客户机发送一个整数。我有一个用C编写的客户端,它连接到服务器并打印出接收到的整数

我的问题是结果各不相同。执行客户机时,大约有一半的时间我得到了正确的结果(234),但其他时间我得到了8323072

这是服务器:

class TCPServer {
  public static void main(String args[]) throws Exception {
     ServerSocket welcomeSocket = new ServerSocket(6789);

     while(true)
     {
        Socket connectionSocket = welcomeSocket.accept();
        System.out.println("welcomeSocket.accept() called");
        DataInputStream inFromClient = new DataInputStream(connectionSocket.getInputStream());
        DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

        outToClient.writeInt(234);
     }
  }
}

这是客户:

int main(int argc, char *argv[])
{
    if(argc != 4){
        printUsage();
        return;
    }

    char* serverIP = argv[1];
    char* serverPortC = argv[2];
    char* integerToSendC = argv[3];

    int serverPort = atoi(serverPortC);
    int integerToSend = atoi(integerToSendC);

    int socketDesc = socket(AF_INET, SOCK_STREAM, 0);

    if(socketDesc < 0) {
        printf("Error when creating socket\n");
        return;
    } 

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(serverPort);
    inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);

    int connection = connect(socketDesc, (struct sockaddr*) &serverAddr, sizeof serverAddr);

    if(connection < 0) {
        printf("Error when establishing connection\n");
        return;
    }

    char intBuffer[4];

    if(recv(socketDesc, intBuffer, sizeof intBuffer, 0) == -1){
        printf("Error while receiving Integer\n");
    }

    int receivedInt = ntohl(*((int *) &intBuffer));

    printf("Received int: %d\n", receivedInt);

    close(socketDesc);
}
intmain(intargc,char*argv[])
{
如果(argc!=4){
打印用法();
返回;
}
char*serverIP=argv[1];
char*serverPortC=argv[2];
char*integerToSendC=argv[3];
int serverPort=atoi(serverPortC);
int integerToSend=atoi(integerToSendC);
int socketDesc=套接字(AF_INET,SOCK_STREAM,0);
如果(socketDesc<0){
printf(“创建套接字时出错\n”);
返回;
} 
serverAddr中的结构sockaddr\u;
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=htons(serverPort);
inet\u pton(AF\u inet、serverIP和serverAddr.sin\u addr);
int connection=connect(socketDesc,(结构sockaddr*)&serverAddr,大小为serverAddr);
如果(连接<0){
printf(“建立连接时出错\n”);
返回;
}
char intBuffer[4];
if(recv(socketDesc,intBuffer,intBuffer的大小,0)=-1){
printf(“接收整数时出错\n”);
}
int receivedInt=ntohl(*(int*)和intBuffer));
printf(“收到的整数:%d\n”,receivedInt);
关闭(socketDesc);
}
提前感谢您的帮助

编辑: 所以最后我做了这样的事情,只为那些有同样问题的人:

while(receivedBytes < 4){
    int readBytes = read(receiverSocket, &intBuffer, (sizeof intBuffer) - receivedBytes, receivedBytes);
    receivedInteger += (intBuffer << (8*receivedBytes));
    receivedBytes += readBytes;
}
while(接收字节<4){
int readBytes=read(receiverSocket和intBuffer,(intBuffer的大小)-receivedBytes,receivedBytes);

receivedInteger+=(intBuffer您的问题可能是由于各种数据类型的子边界造成的

在Java中,4个字节分配给
int
,2个字节分配给
short

在C语言中,4个字节代表
long
,2个字节代表
int

这意味着
javaint
->
clong
javashort
->
cint

现在这取决于你的优先权在哪里

如果您想用Java执行密集的数学计算并通过套接字将结果发送到C,我建议您使用
Javaint->Clong

如果您只想发送少量的数字,并用C语言完成密集的计算,请执行
Javashort
->
cint
转换


希望对您有所帮助。

您能确保在客户端收到了
sizeof intBuffer
字节吗?不,您不能,因为
recv()
返回的字节可能会少于请求的字节

只要接收到的字节数少于请求的字节数且未发生错误,则修改代码以循环执行
recv()

请注意,
recv()
ing
0
bytes表示连接已被另一端关闭

还要确保服务器端以网络字节顺序发送


另外^2:初始化变量是个好主意(
intBuffer
此处),至少在开发阶段,会说:在调优阶段之前。

可能是因为Java和C及其相关子边界中为
int
分配了多少字节。尝试发送少量数字。如果Java为int分配了4个字节,C分配了2个字节。因此,在C中,范围要小得多,该数字是2**16*127(即第三个字节全部为1,底部两个字节全部为0)@LittleChild我也这么认为,但至少在32位运行时发送四个字节似乎非常清楚。您的强制转换看起来很糟糕,更不用说非英特尔硬件上总线错误的主要位置了。您是否考虑过只读取
int32_t
ntohl()之后返回的值
0x7F0000
。也就是说,127在第三个八位组结束。我很想知道
ntohl()之前是什么样子
看起来你有时只能得到部分读取,但即使这样,我也希望在那里至少看到一个0xEA。在C语言中,在我的计算机中,
int
有4个字节。请看。
writeInt
似乎总是以大尾形式写入4个字节。只要它在C端作为4字节
正确地重新组装int
我希望这是正确的。@WhozCraig我不是用C编程的。我只是指维基百科上基本数据类型的大小,它说C分配16位(2字节)因此,我的答案是正确的。如果答案中有错误,或者一开始就错了,请告诉我。我会立即删除它,以免混淆答案OP@LittleChildC中int的大小取决于编译器设置和目标体系结构。它肯定可以是32位,OP似乎表明,在他的例子中,它是最小值符合
int
标准(C99§5.2.4.2.1)的大小为16位(15+1符号)。但该标准仅要求将值表示作为最低遵从性要求。如今,几乎所有非嵌入式C编译器都至少使用32位
int
,有些使用64位。Wiki可能只列出了标准的最低要求。它没有解释收到的值:
123
映射到网络上的
007b
接收的值
8323072
7F 00
。即使读取了1个字节,也不应该是
7F
@ValeriAtamaniouk:很可能是另一侧挂断了连接,
recv()
0
返回,因此不会记录任何错误消息,并且为
receivedInt
打印的
8323072
只是垃圾,因为
intBuffer
在传递到
recv()之前没有初始化
。可能是,但这与计数器部件源不完全匹配:DataOutputStream外壳在关闭前发送4个字节。感谢您的支持