He hecho 2 programas de sockets en C++.
Consiste enviar la cadena "hola" desde un ordenador a otro y hacer que lo muestre en la pantalla del otro ordenador.
Lo he conseguido hacer pero el problema es que el 80% de las veces los datos llegan corruptos. Esto me extraña por que según tengo yo entendido los sockets de flujo usan el protocolo TCP y en este protocolo es el mismo el que se encarga de que lleguen los resultados adecuadamente.
¿Por que sucede esto?¿Como se puede evitar?
Datos: un ordenador es linux y el otro es windows. No estoy usando datagramas.
Si pero podrias poner el code?
Si, claro(aunque no creo que sea necesario):
1º:
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<sys/types.h>
#include<winsock.h>
#include<conio.h>
int main(){
{
WSADATA wsaData; /* Si esto no funciona */
//WSAData wsaData; /* prueba esto en su lugar */
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
}
///////////////////////////////////////////////////////////////////
struct sockaddr_in my_addr, they_addr;
SOCKET sockfd, newfd;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1){
printf("error en socket");
std::cin.get();
exit(-1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(54332);
if(my_addr.sin_addr.s_addr = htonl(INADDR_ANY)==-1){
printf("error en ip\n");
std::cin.get();
exit(-1);
}
memset(&(my_addr.sin_zero), '\0', 8);
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))==-1){
printf("error en bind()");
std::cout<<WSAGetLastError()<<std::endl;
std::cin.get();
exit(-1);
}
if(listen(sockfd, 10)==-1){
printf("error en listen()");
getch();
exit(-1);
}
int size_sockaddr=sizeof(sockaddr);
newfd=accept(sockfd,(struct sockaddr *)&they_addr, &size_sockaddr);
int bytes_sent;
//send(newfd, "hola", 5, 0);
do{bytes_sent=send(newfd, "hola", 5, 0);}
while (bytes_sent!=5);
WSACleanup();
printf("todo en orden\n");
getchar();
}
2º:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<netinet/in.h>
int main(){
int sockfd;
struct sockaddr_in dest_addr;
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if(sockfd==-1){
printf("error en el socket");
std::cin.get();
return -1;
}
dest_addr.sin_family=AF_INET;
dest_addr.sin_port=htons(54332);
dest_addr.sin_addr.s_addr=inet_addr("192.168.1.112");
if(dest_addr.sin_addr.s_addr==-1){
printf("error en ip");
getchar();
return -1;
}
memset(&(dest_addr.sin_zero),0, 8);
if(connect(sockfd, (struct sockaddr*)&dest_addr, sizeof(struct sockaddr))==-1){
printf("error en conect");
getchar();
return -1;
}
char cadena[5];
recv(sockfd, &cadena, 5, 0);
cadena[4]=0;
std::cout<<cadena<<std::endl;
printf("todo en orden\n");
}
¿Y por que no lo has puesto en el foro de C/C++?
PD: Luego miro el code que ahora voy a jugar un poquito :P
Por que a pesar de estar escrito en C++ la duda no tiene que ver en absoluto con C++. Tiene que ver con la programación de sockets. xD
Exactamente ::) Necesitaria ver el code para ver si tiene algo que lo provoque. Los sockets se acaban al compilar xD no tienen vuelta de hoja...
Hola tuket, yo probaría a enviar los datos de esta forma para ver si es este el problema.
char buff[] = "hola";
send(newfd, buff, 5, 0);
Si tengo tiempo, luego pruebo los programas.
Saludos.
Podrias empezar mirando codes de sockets que hay en el foro de C/C++
Hola, gracias por responder.
CitarHola tuket, yo probaría a enviar los datos de esta forma para ver si es este el problema.
Código
char buff[] = "hola";
send(newfd, buff, 5, 0);
Si tengo tiempo, luego pruebo los programas.
Saludos.
Eso ya lo probé, pasa lo mismo: la gran mayoría de las veces los datos llegan corruptos. Yo intuyo que se debe de hacer alguna comprobación pero no se.
http://foro.elhacker.net/ejercicios/ejercicios_en_c-t34911.0.html
Sockets
Bueno. Ya que nadie entiende lo que se pregunta lo voy a repetir de otra manera.
Segun wikipedia:
CitarTCP
El protocolo garantiza que los datos serán entregados en su destino sin errores y en el mismo orden en que se transmitieron.
Lo que significa que si envió los datos por TCP tienen que llegar seguro correctamente.
Como dice esta pagina(http://www.fismat.umich.mx/mn1/manual/node24.html):
CitarSocket de flujo
da un flujo de datos de dos vías, confiable, y sin duplicados sin límites de grabación. El flujo opera en forma parecida a una conversación telefónica. El tipo del socket es SOCK_STREAM, el cual en el dominio de Internet usa TCP (Transmission Control Protocol).
SOCK_STREAM usa el protocolo TCP lo que significa que la cadena "hola" tiene que llegar por cojones al ordenador opuesto(de hecho en ocasiones si que llega).
Mi pregunta es: ¿Por que demonios no llega?¿Se debe a la recepción?¿Wikipedia miente?¿Hay interferencias?¿los extraterrestres están jodiéndome manipulando los datos?
XD espero que ahora se entienda mejor
PD: gracias por el link Sagrini pero no se a que viene eso.
tuket, el protocolo TCP/IP no falla. Lo que falla son los programas, o el cliente o el servidor.
Saludos.
Es bueno saberlo :)
Te faltó cerrar el socket(closesocket/shutdown en wsock) quizá sea eso(código 1).
http://msdn.microsoft.com/en-us/library/bb530744%28v=VS.85%29.aspx (http://msdn.microsoft.com/en-us/library/bb530744%28v=VS.85%29.aspx)
Edito: Por cierto, en el segundo código no miras si da error, si devuelve -1 miras el errno con strerror(errno) y te hubiera dado mas información de lo que pasa. Que lo sepas pa la próxima, en windows no se como se hace pero seguro hay forma.
Nada ya esta solucionado dejo el código cambiado por si a alguien le interesa:
#include<windows.h>
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<sys/types.h>
#include<winsock.h>
#include<conio.h>
int main(){
{
WSADATA wsaData; /* Si esto no funciona */
//WSAData wsaData; /* prueba esto en su lugar */
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
}
///////////////////////////////////////////////////////////////////
struct sockaddr_in my_addr, they_addr;
SOCKET sockfd, newfd;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1){
printf("error en socket");
std::cin.get();
exit(-1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(54336);
if(my_addr.sin_addr.s_addr = htonl(INADDR_ANY)==-1){
printf("error en ip\n");
std::cin.get();
exit(-1);
}
memset(&(my_addr.sin_zero), '\0', 8);
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))==-1){
printf("error en bind()");
std::cout<<WSAGetLastError()<<std::endl;
std::cin.get();
exit(-1);
}
if(listen(sockfd, 10)==-1){
printf("error en listen()");
getch();
exit(-1);
}
int bytes_sent;
int size_sockaddr=sizeof(sockaddr);
while(1){
newfd=accept(sockfd,(struct sockaddr *)&they_addr, &size_sockaddr);
//send(newfd, "hola", 5, 0);
bytes_sent=send(newfd, "mola", 5, 0);
closesocket(newfd);
}
WSACleanup();
printf("todo en orden\n");
getchar();
}