【问题标题】:C99 client communicating with a Java ServerC99 客户端与 Java 服务器通信
【发布时间】:2012-05-24 04:03:25
【问题描述】:

我正在尝试让 C99 客户端与 Java 服务器进行通信。但是,Java 服务器接收的数据与传输的数据不同。 (即@x�@Óf/ú.��@¨������������������Û¢ÁBp'ˇ¡`Ôf/)

我考虑过这是一个编码问题,但我遇到了障碍。我已经尝试测试这两个程序,得出的结论是 Java 服务器能够与 Java 客户端通信,而 C 客户端能够与 C 服务器通信。

但是我无法让 Java 服务器与 C 客户端通信。

Java 代码:

serverSocket = new ServerSocket(port);  
Socket sock = serverSocket.accept();                               

BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

String inputString = in.readLine();
System.out.println(inputString);

C 代码:

struct sockaddr_in sin;
struct hostent *host;

host = gethostbyname(hostname);

bzero(&(sin.sin_zero),8); 
sin.sin_port = htons(port);
sin.sin_addr = *((struct in_addr *)host->h_addr);
sin.sin_family = AF_INET;

sock = socket(AF_INET, SOCK_STREAM, 0);

if(connect(sock, (struct sockaddr *)&sin,sizeof(struct sockaddr_in)) == -1)

...

send(sock, &message, strlen(message)+1, 0);

编辑:我尝试在两台主机之间发送“TEST”一词,但没有成功。

已修复:在传递消息变量时,我在消息变量前面有一个 & 号。

应该是:

send(sock, message, strlen(message)+1, 0);

【问题讨论】:

  • 来自 C 的消息的编码是什么?
  • 那么我的回答是正确的 ;)

标签: java c sockets


【解决方案1】:

我不确定 C99 是否提供了编码标准,但我想它是特定于实现的。例如,它可能是US-ASCII

发生的情况是 Java InputStreamReader(或输出)使用在操作系统或 Java 安装(不确定位置)中指定的默认字符集,因此与 C 程序使用的字符集相比可能会有所不同。

你能做的最好的事情就是测试各种编码,InputStreamReader 类确实提供了一个特定的构造函数:

public InputStreamReader(InputStream in, Charset cs)

您可以在其中指定要使用的字符集。查看here 了解可能的字符集。

【讨论】:

  • C 客户端根据 nl_langinfo(CODESET) 使用 US-ASCII 字符集,因此这不是字符编码问题。我还强制 Java 服务器使用 InputStreamReader 使用此字符集,但没有成功。
【解决方案2】:

如果我没记错的话,你有类似的东西:

char *message = "Hello";

当您发送时:

send(sock, &message, strlen(message)+1, 0);
           |
           +---- Err.

您发送消息的地址而不是消息本身,进一步将长度设置为消息的长度并使用垃圾填充。

如果您改为这样做:

send(sock, message, strlen(message)+1, 0);

它应该可以工作。

或者使用char message[] = "Hello"; ...


要进一步剖析服务器数据,您可以执行以下操作:

        int i = 0;
        for (char ch : inputString.toCharArray()) {
            System.out.printf("%2d: 0x%02X o%03o %3d %c%n",
                i++,
                (int)ch & 0xff,
                (int)ch & 0xff,
                (int)ch & 0xff,
                Character.isISOControl(ch) ? '.' : ch
            );
        }

        buf = inputLine.getBytes(/* charset  */);
        for (i = 0; i < buf.length; ++i) {

等等

Client siad: Hello
 0: 0x00 o000   0 .
 1: 0x48 o110  72 H
 2: 0x65 o145 101 e
 3: 0x6C o154 108 l
 4: 0x6C o154 108 l
 5: 0x6F o157 111 o

使用&消息:

Client said: `�
 0: 0x60 o140  96 `
 1: 0xEF o357 239 ￯
 2: 0xBF o277 191 ﾿
 3: 0xBD o275 189 ᄑ
 4: 0x04 o004   4 .
 5: 0x08 o010   8 .

另一个黑客/调试/可以做的事情是:

    while (true) {
        in.mark(128);
        if ((inputLine = in.readLine()) == null)
            continue;

        System.out.println("Response: " + inputLine);

        in.reset();
        i = 0;
        while (in.ready()) {
            c = in.read();
            System.out.printf("%2d: 0x%02X o%03o %3d %c%n",
                i++,
                c, c, c,
                Character.isISOControl((char) c) ? '.' : (char)c
            );
        }
    }

【讨论】:

    【解决方案3】:

    您还必须查看字节序差异:Java 使用network order,而 C 主机可能不使用。 ByteBuffer,插图here,可能会有所帮助。

    【讨论】:

      【解决方案4】:

      你的问题看起来像字节对齐

      在您的C 客户端中,您需要将主机转换为网络字节顺序

      使用

      uint32_t htonl(uint32_t hostlong);
      
      uint16_t htons(uint16_t hostshort);
      
      uint32_t ntohl(uint32_t netlong);
      
      uint16_t ntohs(uint16_t netshort);
      

      【讨论】:

      • 我发送的是文本,而不是原始数字。
      • 请参考这个问题来发送字符数组stackoverflow.com/q/526030/143897
      • 从客户端向服务器发送单词“test”不起作用。该消息没有任何数字,所以我怀疑这是问题所在。
      猜你喜欢
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      相关资源
      最近更新 更多