通过套接字从Java向C发送int-奇怪的结果
我有一个用Java编写的简单服务器,它只向连接的客户机发送一个整数。我有一个用C编写的客户端,它连接到服务器并打印出接收到的整数 我的问题是结果各不相同。执行客户机时,大约有一半的时间我得到了正确的结果(234),但其他时间我得到了8323072 这是服务器:通过套接字从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
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()
ing0
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个字节。感谢您的支持