java - 为什么我不能不等待就将 int 从 java 发送到 C?

标签 java c sockets

我遇到了一个奇怪的问题。我正在尝试编写 C 客户端和 Java 服务器之间的接口(interface)。为此,我用 Java 编写了一个网关(它使用 RMI 与服务器通信)。几乎一切正常,但我试图从网关向 C 客户端返回一些整数。这是代码:

Java 网关:

import java.net.Socket;
import java.net.ServerSocket;
import java.net.MalformedURLException;
import java.io.BufferedReader;
import java.net.InetSocketAddress;
import java.io.InputStreamReader;
import java.io.DataOutputStream;
import java.lang.System;

public class hotelgw{

  public static final int PORT = 4242;
  public static final int BACKLOG = 5;
  public static final int MAX_ARGS = 5;

  public hotelgw(){
    InetSocketAddress address;
    ServerSocket socket = null;
    try{
      address = new InetSocketAddress(PORT);
      socket = new ServerSocket(PORT,BACKLOG);
    }catch (Exception e){
      System.out.println("Error: "+e);
      System.exit(1);
    }

    while(true){

      Socket newsock = null;
      try{
       newsock =  socket.accept();
      }catch (Exception e){
        System.out.println("Error: "+e);
        System.exit(1);
      }

      BufferedReader in = null;
      DataOutputStream out = null;

      try{
        in = new BufferedReader(new InputStreamReader(newsock.getInputStream()));
        out = new DataOutputStream(newsock.getOutputStream());
      }catch (Exception e){
        System.out.println("Error: "+e);
        System.exit(1);
      }


      String[] init_args = new String[MAX_ARGS];
      int i = 0;
      String c;

      try{
        while(!(c = in.readLine()).equals("end")){
          System.out.printf("%s",c);
          init_args[i] = c;
          i++;
        }
      }catch (Exception e){
        System.out.println("Error: "+e);
        System.exit(1);
      }

      for(int j=0;j<init_args.length;j++){
        System.out.printf("init_args[%d] = %s\n", j, init_args[j]);
      }

      int counter = 0;
      for(int j=0;j<init_args.length;j++){
        if(init_args[j] != null){
          counter++;
        }
      }

      String[] final_args = new String[counter];
      for(int j=0;j<counter;j++){
        final_args[j] = init_args[j];
      }

      if(final_args[1].equals("list")){
        int[] list = hotelclient.get_list(final_args);
        System.out.println("list received in hotelgw.java");
        for(int j=0;j<list.length;j++){
          try{
            out.writeInt(list[j]);
          }catch (Exception e){
            System.out.println("Error writing to socket: " + e);
            System.exit(1);
          }
        }
      }


      try{
        in.close();
        newsock.close();
      }catch (Exception e){
        System.out.println("Error: "+e);
        System.exit(1);
      }
    }
  }
}

C 客户端:

#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define PORT 4242
#define TYPES_OF_ROOMS 3
#define BUFFER_SIZE 64

/*Writes message to socket*/
ssize_t writen(int fd, const void *vptr, size_t n)
{
  size_t nleft;
  ssize_t nwritten;
  const int *ptr;

  ptr = vptr;
  nleft = n;
  while(nleft>0){
    if ( ((nwritten = write(fd,ptr,nleft)) <= 0)){
      if (errno == EINTR)
        nwritten = 0;
      else
        return -1;

    }
    nleft -= nwritten;
    ptr += nwritten;
  }
  return n;
}


int create_socket(char* address){
  struct hostent *server_address;
  struct in_addr *addr;
  struct sockaddr_in server_addr;
  socklen_t addrlen;
  char* ip;

  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if(sockfd<0){
    perror("Error creating socket");
    exit(1);
  }

  server_address = gethostbyname(address);
  if(server_address == NULL){
    fprintf(stderr, "Server not found!\n");
    exit(1);
  }else{
    addr = (struct in_addr*) server_address->h_addr_list[0];
  }

  ip = inet_ntoa(*addr);

  server_addr.sin_family  =  AF_INET;
  server_addr.sin_port    =  htons(PORT);
  server_addr.sin_addr.s_addr  =  inet_addr(ip); 

  addrlen = (socklen_t) sizeof(struct sockaddr_in);

  if(connect(sockfd,(struct sockaddr *) &server_addr, addrlen)){
    perror("Error connecting to server");
    exit(1);
  }

  return sockfd;
}


int main(int argc, char** argv){
  int sockfd, err, i, type1=0, type2=0, type3=0;
  int int_buf[TYPES_OF_ROOMS];
  char string_buf[BUFFER_SIZE];
  char newline = '\n';
  char *end = "end";

  if(argc == 1){
    printf("Usage: hotelgwclient <address> {list,guests,book} [room type] [guest name]\n");
    exit(1);
  }

  sockfd = create_socket(argv[1]);
  printf("Socket created\n");


  if(strcmp(argv[2], "list")==0){
    if(argc != 3){
      printf("Usage: hotelgwclient <address> list\n");
      exit(1);
    }


    printf("list initiated\n");
    writen(sockfd, argv[1], strlen(argv[1]));
    writen(sockfd, &newline , sizeof(newline));
    writen(sockfd, argv[2], strlen(argv[2])); 
    writen(sockfd, &newline, sizeof(newline));
    writen(sockfd, end, strlen(end));
    writen(sockfd, &newline, sizeof(newline));
    printf("Written to socket\n");

    err = read(sockfd, &type1, sizeof(int));
    err = read(sockfd, &type2, sizeof(int));
    err = read(sockfd, &type3, sizeof(int));

    printf("Read from socket\n");
    if(err<0){
      perror("Error reading from socket");
      exit(1);
    }
    /*
    for(i=0;i<TYPES_OF_ROOMS;i++){
      printf("%d\t",int_buf[i]);
    }
    */
    type1 = htonl(type1);
    type2 = htonl(type2);
    type3 = htonl(type3);

    printf("%d\t",type1);
    printf("%d\t",type2);
    printf("%d\t",type3);
    printf("\n");
    return 0;
  }

  printf("Command not recognized.\nUsage: hotelgwclient <address> {list,guests,book} [room type] [guest name]\n");
  exit(1);
}

(注意,我知道它很乱,我会在它工作时清理它:))。

问题是每当我调用 list 方法时,C 试图读取响应(三个整数),它只会读取一个字节,而不是四个。如果我在从套接字读取之前添加 sleep() 调用,则此问题已修复。有谁知道发生了什么以及我应该如何解决它?!

谢谢!

最佳答案

我怀疑问题在于您假设当最小值始终为 1 时(即使在 Java 中),您将读取尽可能多的数据

为什么你在其他字节之前得到一个字节是因为你正在使用没有 BufferedOutputStream 的 DataOutputStream 所以它一次发送一个字节。使用此解决方法可能很诱人,但它只是隐藏了您需要能够一次正确读取一个字节的潜在问题,因为这始终是可能的。

关于java - 为什么我不能不等待就将 int 从 java 发送到 C?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12974228/

相关文章:

c++ - putc 和 ungetc 有什么区别?

Java String类的奇怪特性

java - 如何从现有代码制作简单的工作流程?

c - 位操作谜题

计算第二个RC4 key 字节为0x00的事件的频率

python - 远程连接不起作用。无法使用python套接字连接到服务器

java - JPA/Hibernate - x 实例的标识符被更改异常

java - SLF4J 日志级别作为参数

c - tcp客户端如何理解服务器状态码

c++ - Zlib C++ boost 套接字数据