【问题标题】:send an integer from a C client to a Java server从 C 客户端向 Java 服务器发送一个整数
【发布时间】:2013-05-03 15:17:38
【问题描述】:

我使用此代码将整数从我的 Java 客户端发送到我的 Java 服务器

int  n = rand.nextInt(50) + 1;
            DataOutputStream dos = new DataOutputStream(_socket.getOutputStream());
            dos.writeInt(n);

我用这段代码在服务器中读取它

DataInputStream din = new DataInputStream(socket.getInputStream());
        int ClientNumber= din.readInt();
        System.out.println(ClientNumber);


        ClientNumber++;
       DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
       dos.writeInt(ClientNumber);

       String randomString= getRandomValue(10,20);
       dos.writeUTF(randomString);

它工作得很好,但现在我想写一个 C 客户端 我试过这段代码

  #include <stdio.h>
#include <errno.h>
#include <signal.h>

#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define SERVEURNAME "localhost" // adresse IP de mon serveur

int to_server_socket = -1;

void main ( void )
{

    char *server_name = SERVEURNAME;
    struct sockaddr_in serverSockAddr;
    struct hostent *serverHostEnt;
    long hostAddr;
    long status;
    char buffer[512];

    bzero(&serverSockAddr,sizeof(serverSockAddr));
    hostAddr = inet_addr(SERVEURNAME);
    if ( (long)hostAddr != (long)-1)
        bcopy(&hostAddr,&serverSockAddr.sin_addr,sizeof(hostAddr));
    else
    {
        serverHostEnt = gethostbyname(SERVEURNAME);
        if (serverHostEnt == NULL)
        {
            printf("gethost rate\n");
            exit(0);
        }
        bcopy(serverHostEnt->h_addr,&serverSockAddr.sin_addr,serverHostEnt->h_length);
    }
    serverSockAddr.sin_port = htons(8071);
    serverSockAddr.sin_family = AF_INET;

    /* creation de la socket */
    if ( (to_server_socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        printf("creation socket client ratee\n");
        exit(0);
    }
    /* requete de connexion */
    if(connect( to_server_socket,
               (struct sockaddr *)&serverSockAddr,
               sizeof(serverSockAddr)) < 0 )
    {
        printf("demande de connection ratee\n");
        exit(0);
    }
    /* envoie de donne et reception */
    int value = htons( 4 );
    write( to_server_socket, &value, sizeof( value ) );

    printf(buffer);


}

但它不起作用。我使用 Eclipse 来编译 java 代码并为 C 代码(客户端)运行服务器和 xcode,但我认为问题不存在

编辑: 我在服务器上遇到错误

java.net.SocketException:管道损坏 java.net.SocketOutputStream.socketWrite0(本机方法)在 java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92) 在 java.net.SocketOutputStream.write(SocketOutputStream.java:115) 在 java.io.DataOutputStream.writeInt(DataOutputStream.java:182) 在 ServiceRequest.run(ServiceRequest.java:36) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)

我认为这是因为我的服务器等待一个整数,但它不是...?

【问题讨论】:

  • 获取write返回的值。如果-1,则检查errno

标签: java c sockets


【解决方案1】:

这句话中有两件事让我大吃一惊……

write(to_server_socket,"4",4);

1) "4" 不是整数,它是一个以空字符结尾的字符串(嗯,好吧,它是一个整数,但它不是你“想要”做的我想的)

2) 您以主机字节顺序发送值,它可能与网络字节顺序相同也可能不同

int value = htons( 4 );
write( to_server_socket, &value, sizeof( value ) );

然而,除此之外,来自 java socketWrite() 的“管道损坏”错误往往表明您的发送端(C 应用程序)已关闭套接字,而您的 java 端仍在尝试写入。

您的 C 客户端代码正在打开套接字,写入它然后立即打印一个您从未填充过任何内容的缓冲区并退出程序。一旦程序退出,您为其创建的套接字就会关闭,因此 Java 服务器中的“管道损坏”错误。您需要读取服务器的回复...

int value = htonl( 4 );
int reply = 0;

if( send( to_server_socket, &value, sizeof( value ), 0 ) != sizeof( value ) )
{
    printf( "socket write failed: %s", strerror( errno ) );
    exit( -1 );
}

if( recv( to_server_socket, &reply, sizeof( reply ), MSG_WAITALL ) != sizeof( reply ) )
{
    printf( "socket read failed: %s", streror( errno ) );
    exit( -1 )
}

printf( "got reply: %d\n", ntohl( reply ) );

在单独的说明中...您表示您在服务器上收到 262144...是在我建议的更改之前还是之后? 262144 是 0x00040000 - 所以......你确实得到了 4,只是不是你期望收到它的地方。因此,您使用的是 32 位整数(我应该意识到这一点),这意味着您要使用 htonl()ntohl() 而不是 htons()ntohs(),它们是短整数转换。

【讨论】:

  • 我会假设您的 C 应用程序在您发送后退出?从您的 java 应用程序写入的 broken pipe 错误意味着 C 应用程序用于发送整数的套接字不再存在。我刚刚编辑了我的答案,提到在您编辑问题以包含错误输出之后。
  • 不,我没有关闭套接字,我只有 printf(buffer);显示服务器的答案。在服务器中我没有收到 4 而是 262144
  • 你的代码不完整,所以我看不出你哪里出错了。我只能看到你将 int 发送到服务器,我看不到你是如何得到回复的。
  • 谢谢你现在它工作但只适用于 int,我不能将 ntohl 用于 String 吗?
  • No... ntohl() 用于转换 32 位整数值的字节顺序(在这种情况下,从 intel 上的 little-endian 到 big-endian 网络字节顺序。字符串总是以相同的字节顺序发送。所以你不需要这样做。send( socket, myString, strlen( myString )+1, 0 ) 将通过套接字发送一个带有空终止符的完整字符串。
猜你喜欢
  • 1970-01-01
  • 2016-07-13
  • 2015-12-26
  • 2016-02-23
  • 2015-02-17
  • 2014-04-08
  • 2015-10-04
  • 2016-02-04
  • 1970-01-01
相关资源
最近更新 更多