错误的通信c服务器和java客户端
我试图做一个tcp echo服务器与C中的多线程支持和用java编写的客户端,都使用套接字进行通信。通信开始很好,但不知何故,在服务器和客户端之间传递的字符串在尝试几次之后开始“损坏”(添加新的行字符或发送的旧消息片段)。 我搜索了论坛,并认为问题是C的空字符,但在Java中删除它根本没有任何区别。 这里是为C服务器代码:错误的通信c服务器和java客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/limits.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <time.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
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 <dirección> <puerto>");
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分配的接收缓冲区,并且在接收下一条消息之前也不重新初始化缓冲区。在阅读每条消息之前,您应该用零覆盖缓冲区。
我的第一个建议是检查您的当前端口是否被任何其他应用程序使用。简单的做法是构建一个回显服务器(例如,不是严格意义上的回显服务器,但是)并尝试连接并查看它是否成功连接到对方。
//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。我希望这是有帮助的。
使用的端口是6256,其他任何人都没有使用该端口(无论如何使用netstat),但我会尝试您的两条建议并通知您。非常感谢。 – user2329051 2013-04-28 13:17:32
不用担心= D祝你好运! – Jason 2013-04-28 13:30:56
因为你们俩都是啤酒:D // @Nemanja – user2329051 2013-04-28 15:44:44
这就是问题:)。我倾向于用“java方式”思考更多的字符串,而不是像char数组。 C新手错误。我现在正在做一个memset(mensaje_env,'/ 0',100)将所有的缓冲区设置为空。另外(谢谢@TemporaryNickName)阅读像字节这样的信息给了我更多的工作自由。 – user2329051 2013-04-28 15:31:35