He estado buscando y no he podido encontrar una solución a este problema en particular. Perdónenme si se trata de un error de principiante, recién salido de la escuela, así que leo tantos libros como puedo para ponerme al día con la programación de dispositivos móviles.Datos basura transmitidos en WiFi Conexión TCP desde el escritorio a Android
El objetivo: datos de transmisión desde un servidor de socket basado en PC a un cliente basado en Android de forma inalámbrica (802.11 b/g), que será entonces proceso de dichos datos para la salida al usuario.
El problema: Se está recibiendo una gran cantidad de datos erróneos de basura en las memorias intermedias de flujo de entrada en el teléfono Android.
El procedimiento: He escrito y/o modificado tres piezas de código diferentes. Primero es el programa del servidor que se ejecuta en mi computadora portátil. El código fuente original se puede encontrar aquí: beej.us/guide/bgnet/examples/server.c (¡gracias a Beej por su código fuente!). Lo modifiqué para eliminar advertencias/errores, y agregué mi propio bucle continuo de entrada de datos para fines de prueba. Aquí está el código modificado:
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno; //, clilen;
//Modified this fromt he original author's code, as
//the function is looking for clilen to be of type
//socklen_t, not int
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
//Added this for some clarity
printf("Starting to listen on the socket now..\n");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
//Let me know a socket connection has been established
printf("Socket established!\n");
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
//Don't want this socket to block and read, only to write
//Modified from the original author
//n = read(newsockfd,buffer,255);
//if (n < 0) error("ERROR reading from socket");
//printf("Here is the message: %s\n",buffer);
//n = write(newsockfd,"Hello, socket!",18);
const int SIZE_OF_STRING = 30;
char string[SIZE_OF_STRING];
int i = 0;
for (i = 0; i < SIZE_OF_STRING; ++i)
{
string[i] = '\0';
}
//Ask input from the user until the word "quit" is seen
//then close the socket
while (!strstr(string, "quit"))
{
printf("Please enter something to send to the phone.\n");
scanf("%s", string);
strcat(string, "\n");
n = write(newsockfd, string, sizeof(string));
if (n < 0) error("ERROR writing to socket");
}
printf("\n\nexiting..\n");
close(newsockfd);
close(sockfd);
return 0;
}
Y aquí es el código de Android:
public class SmartSawLineDrawSocketThread extends Thread
{
private Handler smartSawMainThreadCommunicationHandle_;
private Socket smartSawSocketHandle_;
private InputStream smartSawSocketInputStreamHandle_;
private BufferedReader smartSawSocketInputBuffer_;
private InputStreamReader smartSawSocketInputStreamReader_;
private boolean threadRunning_ = false;
private boolean isConnected_;
private char buffer[] = new char[50];
//Grab the thread's communication handle for use with sending messages to the UI
//Thread
public SmartSawLineDrawSocketThread(Handler handle)
{
smartSawMainThreadCommunicationHandle_ = handle;
threadRunning_ = true;
isConnected_ = false;
}
//Attempt a connection to the host
public int SmartSawLineDrawSocketThreadConnect(String hostIP, String hostPort)
{
int rval = 0;
Log.i("info", "hostIP = " + hostIP);
Log.i("info", "hostPort = " + Integer.parseInt(hostPort.trim()));
try
{
smartSawSocketHandle_ = new Socket(hostIP.trim(), Integer.parseInt(hostPort.trim()));
if (rval == 0)
{
smartSawSocketInputBuffer_ = new BufferedReader(new InputStreamReader(smartSawSocketHandle_.getInputStream()));
smartSawSocketInputStreamReader_ = new InputStreamReader(smartSawSocketHandle_.getInputStream());
if (smartSawSocketInputBuffer_ != null)
{
isConnected_ = true;
}
else
{
Log.e("error", "Input buffer pointer was null!");
}
}
}
catch (UnknownHostException e)
{
rval = 1;
Log.i("info", "unknown host message e when connecting:" + e);
e.printStackTrace();
isConnected_ = false;
}
catch (IOException e)
{
rval = 2;
Log.i("info", "unknown IOException e when connecting:" + e);
e.printStackTrace();
isConnected_ = false;
}
catch (SecurityException e)
{
rval = 3;
Log.i("info", "Need to set a security setting somewhere");
}
Log.i("info", "Rval returned with " + rval);
return rval;
}
//Disconnect from the server
public void SmartSawLineDrawSocketThreadDisconnect()
{
try
{
smartSawSocketHandle_.close();
isConnected_ = false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//Once the thread has started running, make sure we're connected, and start
//trying to listen for messages
@Override
public void run()
{
Log.i("info", "Made it into the run() loop of the thread.");
while (threadRunning_)
{
if (isConnected_ == true)
{
try
{
if (smartSawSocketInputStreamReader_.ready() == true)
//(smartSawSocketInputBuffer_.ready() == true)
{
int numread = 0;
numread = smartSawSocketInputStreamReader_.read(buffer);
Log.i("info", "amount of characters read in: " + numread);
Message mainThreadMessage_ = Message.obtain();
Bundle mainThreadDataBundle_ = new Bundle();
mainThreadDataBundle_.putString("Zero", new String(buffer)); //smartSawSocketInputBuffer_.readLine());
mainThreadMessage_.setData(mainThreadDataBundle_);
mainThreadMessage_.setTarget(smartSawMainThreadCommunicationHandle_);
mainThreadMessage_.sendToTarget();
Log.i("info", "Received a string! Sent this to main thread: " + mainThreadDataBundle_.getString("Zero"));
}
}
catch (IOException e)
{
Log.i("info","IO Exception in thread main loop, e was: " + e);
}
}
}
}
}
Tareas y Análisis: puedo trasmitir exitosamente una cadena, pero todo después de eso es basura ininteligible en el Conexión PC-Android. Queriendo hacer mi tarea primero, quería eliminar el código del lado del servidor. Tomé el código del lado del cliente de Beej (beej.us/guide/bgnet/examples/client.c) y lo modifiqué para que fuera un buen oyente. Pude transmitir varias cadenas al cliente en una conexión TCP basada en PC-PC. Redirigí la salida del cliente a un archivo y lo abrí bajo un editor hexadecimal. Y he aquí, no se encontraron datos erróneos. Probé esto con una computadora portátil conectada a un enrutador 802.11b/g que es el servidor, y con una computadora de escritorio fija que es el cliente. Eliminé los problemas de hardware y los problemas de código de prueba en el lado del servidor. DEBE estar en alguna parte de cómo estoy implementando el código del lado del cliente de Android. También probé con la clase BufferedReader para hacer mi entrada, así como el manejo manual de la entrada con una clase InputStreamReader. Ambos reciben la misma salida de basura después de la primera cadena. Esto me lleva a creer que está en algún lugar del flujo de entrada del socket, pero ¿cómo lo arreglaría? ¿Alguien tiene alguna sugerencia?
Este es el código para la prueba en el cliente basado en PC:
/*
** client.c -- a stream socket client demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT "27015" // the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
//Modified from the original to spit out all strings transmitted from the server, then close the socket
//when finished.
while (!strstr(buf, "close"))
{
numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0);
if (numbytes)
{
printf("Received: \n");
printf("%s", buf);
printf("\n");
}
}
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("client: received '%s'\n",buf);
close(sockfd);
return 0;
}
Gracias por la ayuda! Moscro
FYI, si bien no con apoyo oficial puede compilar su prueba de cliente de PC con el NDK de gcc como un ejecutable independiente y pruébalo por teléfono. También algunas versiones de Android tienen un ejecutable de línea de comando netcat (nc) que es ideal para probar en ambos extremos. –
Gracias Chris! Lo investigaré en mi próxima ronda. Ya tengo la infraestructura configurada, así que lo dejo como está por ahora, pero eso será útil más adelante. – moscro