通信ac服务器和java客户端时出错

我正在尝试在C中创建一个带有multithreading支持的tcp echo服务器和用java编写的客户端,两者都使用套接字进行通信。 通信开始很好,但不知何故,在服务器和客户端之间传递的字符串经过几次尝试(添加新的行字符或发送的旧消息片段)后开始“损坏”。 我搜索了论坛,并认为问题是C的空字符,但在java中删除它没有任何区别。 这是C服务器的代码:

#include  #include  #include  #include  #include  /* See NOTES */ #include  #include  #include  #include  #include  #include  #include  #include  #include  struct message { int operacion; int dato; }; int max_attempts; int obtenerMaxAttempts() { FILE *fp; fp = fopen("server.conf", "r"); if (fp == NULL) { perror("Error abriendo fichero"); printf("Errno:%d", errno); } char line[LINE_MAX]; char *aux; while (fgets(line, LINE_MAX, fp) != NULL) { aux = strtok(line, " "); if (strcmp(aux, "maxAttempts") == 0) { aux = strtok(NULL, " "); max_attempts = atoi(aux); } } return (max_attempts); } int obtenerPuerto() { in_port_t puerto; FILE *fp; fp = fopen("server.conf", "r"); if (fp == NULL) { perror("Error abriendo fichero"); printf("Errno:%d", errno); } char line[LINE_MAX]; char *aux; while (fgets(line, LINE_MAX, fp) != NULL) { aux = strtok(line, " "); if (strcmp(aux, "port") == 0) { aux = strtok(NULL, " "); puerto = atoi(aux); } } return (puerto); } void *eco(void *new_sockfd) { int socket = *((int *) new_sockfd); free(new_sockfd); int longitud; char *mensaje_recv, *mensaje_env; mensaje_recv = malloc(100 * sizeof (char)); mensaje_env=malloc(100 * sizeof (char)); while (1) { longitud = recv(socket, (void *) mensaje_recv, 100, 0); printf("Mensaje recibido del cliente: %s", mensaje_recv); strcpy(mensaje_env,mensaje_recv); printf("Mensaje enviado al cliente: %s", mensaje_env); send(socket, (void *) mensaje_env, sizeof (mensaje_env), 0); /* Cerrar el socket */ } } /* Función principal del servidor */ int main(int argc, char *argv[]) { pthread_t idHilo; int error; struct sockaddr_in entrada; entrada.sin_family = AF_INET; entrada.sin_addr.s_addr = htonl(INADDR_ANY); entrada.sin_port = htons(obtenerPuerto()); /* Comprueba que servidorTCP tiene 1 argumento (servidorTCP)*/ if (argc != 1) { printf("Número de parámetros inválido.\n Sintaxis: servidorTCP \n"); exit(EXIT_FAILURE); } /* Creación del socket TCP */ int socketid = socket(AF_INET, SOCK_STREAM, 0); // SOCK_STREAM(conexión tcp, mirar documentación de socket()) if (socketid == -1) { perror("Error creando el socket"); printf("Errno=%d\n", errno); exit(EXIT_FAILURE); } /************************************************************************************/ /* Preparar un nombre local en el puerto especificado: El nombre local */ /* se prepara con la propia dirección de Internet que la sabe el sistema, */ /* y el puerto se obtiene del parámetro recibido */ /************************************************************************************/ /* Asigna nombre local al socket: Asignación de una dirección local */ if (bind(socketid, (struct sockaddr*) &entrada, sizeof (entrada)) == -1) { perror("Error asignando nombre de socket"); printf("Errno=%d\n", errno); exit(EXIT_FAILURE); } int new_sockfd; #define max_queue 10 /* Esperar el establecimiento de alguna conexión */ if (listen(socketid, max_queue) == -1) { perror("Error habilitando socket para conexiones"); printf("Errno=%d\n", errno); exit(EXIT_FAILURE); } struct sockaddr_in remote_addr; int addrlen; addrlen = sizeof (struct sockaddr_in); while (1) { new_sockfd = accept(socketid, (struct sockaddr *) &remote_addr, &addrlen); if (new_sockfd == -1) { perror("Error aceptando la conexión"); printf("Errno=%d\n", errno); exit(EXIT_FAILURE); } int *numero = malloc(sizeof (int)); *numero = new_sockfd; //error = pthread_create(&idHilo, NULL, juego, (void *) numero); error = pthread_create(&idHilo, NULL, eco, (void *) numero); if (error != 0) { perror("No puedo crear thread"); exit(EXIT_FAILURE); } } /* Recibir el mensaje */ } 

这是java客户端的代码:

 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.*; /** * * @author obok */ public class clienteTCP { public static void main(String[] args) throws IOException { /** * Comprobamos el número de parámetros * */ System.out.println(args); System.out.println(args.length); if (args.length != 2) { System.out.println("Número de parámetros inválido"); System.out.println("Sintaxis: clienteTCP  "); return; } int puerto; puerto = Integer.parseInt(args[1]); InetAddress direccion = null; try { direccion = InetAddress.getByName(args[0]); } catch (UnknownHostException ex) { //Logger.getLogger(clienteTCP.class.getName()).log(Level.SEVERE, null, ex); System.out.println("La dirección no es correcta."); } Socket socket = null; System.out.println("Dirección:" + direccion + " Puerto: " + puerto); try { socket = new Socket(direccion, puerto); } catch (IOException ex) { System.out.println("Error de entrada salida creando el socket."); return; //Logger.getLogger(clienteTCP.class.getName()).log(Level.SEVERE, null, ex); } BufferedReader in; String mensaje; mensaje = ""; String mensaje2; in = new BufferedReader(new InputStreamReader(System.in)); //DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream()); PrintWriter outToServer = new PrintWriter(socket.getOutputStream(),true); BufferedReader inFromServer = new BufferedReader(new InputStreamReader( socket.getInputStream())); while (!mensaje.equalsIgnoreCase("salir")) { System.out.println("Introduzca mensaje: "); mensaje = in.readLine(); System.out.println("Mensaje enviado al servidor: "+mensaje); outToServer.println(mensaje); //outToServer.writeBytes(mensaje+"\n"); mensaje2 = inFromServer.readLine(); mensaje2= mensaje2.replaceAll("/0", ""); System.out.println("Mensaje recibido del servidor: "+ mensaje2); } socket.close(); } 

我也尝试调试服务器(使用gdb)和客户端(使用netbeans集成java调试器),但我无法弄清楚它们之间出了什么问题。 任何帮助将非常感谢。

在C代码中,funcion eco,您不初始化使用malloc分配的接收缓冲区,并且在接收下一条消息之前也不会重新初始化缓冲区。 在阅读每条消息之前,您应该用零覆盖缓冲区。

我的第一个建议是检查您当前的端口是否被其他任何应用程序使用。 这样做的简单方法是构建一个echo服务器(示例不是严格意义上的echo服务器,但是)并尝试连接并查看它是否成功连接到彼此。

 //Simple echo server ServerSocket welcomeSocket = new ServerSocket(//your port); Socket connectionSocket = welcomeSocket.accept(); System.out.println("Connection successful"); 

第二个建议是我注意到你目前正在使用BufferedReader和

  mensaje = in.readLine(); 

readline函数。 如果您的C服务器没有发送未通过\ n [新行]结束的字符串,那么它就不会读取和阻止。 然后我建议你使用

 DataInputStream 

并通过指定每次读取的缓冲区大小来使用readFully(byte [])或read(byte [])。 我希望这是有帮助的。