Programación de socket c, solo recibe una línea a la vez
Frecuentes
Visto 863 veces
0
Tengo el problema de recibir solo una línea a la vez en mi lado del cliente. Estoy tratando de encontrar una manera de recibir todo el flujo a la vez. ¿Alguien puede corregir lo que tengo con respecto al problema de recepción? He incluido el código del cliente y una parte del código del lado del servidor que creo que es relevante.
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
FILE *log;
int opt;
int count = 0;
int sock, bytes_received;
char send_data[2048],recv_data[2048];
struct hostent *host;
struct sockaddr_in server_addr;
if(remove("client_log")) ;
if(argc == 2)
{
if(strcmp(argv[1], "-v") == 0)
{
log = fopen("client_log", "a");
opt = 1;
}
else if(strcmp(argv[1], "-V") == 0)
{
log = fopen("client_log", "a");
opt = 2;
}
}
}
else
opt = 0;
host = gethostbyname("127.0.0.0");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(noneya);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Connect");
exit(1);
}
while(1)
{
bytes_received=recv(sock,recv_data,2048,0);
recv_data[bytes_received] = '\0';
if (strcmp(recv_data , "q") == 0 || strcmp(recv_data , "Q") == 0)
{
close(sock);
break;
}
else
{
if(opt != 0)
fprintf(log, "\n Received Data: %s \n", recv_data);
if(opt == 2)
printf("\nReceived Data: %s \n" , recv_data);
}
if(count == 0)
{
printf("Pick an option: \n");
printf("1 - to search by Department only\n");
printf("2 - to search by Department and Class Number\n");
printf("3 - to search more specifically\n");
printf("q or Q - to Quit");
}
printf("\nSEND: ");
gets(send_data);
if(count == 0)
{
count = (int)send_data;
if(count == 3)
count++;
}
else if(count > 0)
count--;
if(opt != 0)
fprintf(log, "\n Sending Data: %s \n", send_data);
if(opt == 2)
printf("\n Sending Data: %s \n" , send_data);
if (strcmp(send_data , "q") != 0 && strcmp(send_data , "Q") != 0)
send(sock,send_data,strlen(send_data), 0);
else
{
send(sock,send_data,strlen(send_data), 0);
close(sock);
break;
}
}
return 0;
}
Aquí está el lado del cliente de las cosas:
case 1:
fread(data, sizeof(sched_record), MAX_RECORD, filePointer);
fclose(filePointer);
char send_data[] = "Enter Department Name";
send(connected, send_data, strlen(send_data), 0);
bytes_received = recv(connected, recv_data, BUF, 0);
recv_data[bytes_received] = '\0';
strcpy(tempDept, recv_data);
for (i=0; i<MAX_RECORD; i++){
if ((strcmp(tempDept, data[i].Dept)==0) && tempCourse != data[i].course){
sprintf(send_data,"%s %d", data[i].Dept, data[i].course);
send(connected, send_data, strlen(send_data), 0);
tempCourse = data[i].course;
}
}
break;
Puedo proporcionar más información si es necesario. Creo que el lado del servidor está bien. Compilé con -Wall y -Wextra y no recibí ninguna advertencia.
2 Respuestas
3
Está recibiendo datos una línea a la vez porque se envía una línea a la vez. Sin embargo, el hecho de que termine saliendo de esta manera es pura suerte; Los flujos TCP se pueden dividir y recombinar arbitrariamente por la pila TCP del cliente, o mediante el almacenamiento en búfer en el otro extremo. Necesita alguna forma de encuadre explícito en la transmisión, por ejemplo, un conteo enviado antes de cada línea, o un \n
al final de una línea.
contestado el 03 de mayo de 12 a las 16:05
1
Para agregar la respuesta de Twilight, lo que ha encontrado aquí es la necesidad de usar un protocolo basado en flujo.
Debido a que TCP no está orientado a mensajes (a diferencia de UDP y otros protocolos de mensajes más exóticos), está enviando y recibiendo un solo flujo de bytes. Básicamente, si tuviera que considerar a su cliente como el escritor de un libro y a su servidor como su lector, entonces en el mundo de TCP se eliminan todos los signos de puntuación :).
Como programador, es su trabajo proporcionar una forma bien definida para poder codificar y/o incrustar dónde termina un mensaje/marco y comienza el siguiente. El uso de líneas nuevas es el método más simple, pero cualquier protocolo basado en TCP usa longitudes, delimitadores o una combinación de los mismos (ver HTTP).
contestado el 03 de mayo de 12 a las 20:05
Perdóname aquí, pero no viendo cómo me ayuda lo que dijiste? ¿Quizás un ejemplo podría ayudar? - c_sostenido
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c sockets or haz tu propia pregunta.
cuando dice "final de una línea", ¿está sugiriendo \n en las declaraciones de sprintf? No estoy siguiendo lo que dices, ¿puedes mostrarme? - c_sostenido
Sí, eso es exactamente lo que quiero decir. De lo contrario, puede recibir todos los datos que envió combinados de esta manera:
"Department 123Department 456Department 789"
- usuario149341Eso no pareció funcionar. Todavía tengo que presionar enter para obtener la siguiente línea de información. - c_sostenido