我一直在四处寻找,还没有找到解决这个问题的办法。原谅我,如果这是一个新手的错误,我刚从学校出来,所以我正在阅读尽可能多的书籍,以赶上移动设备编程。
的目标:将数据从基于PC的套接字服务器无线传输到基于安卓的客户端(802.11 b/g),然后处理这些数据以输出给用户。
问题:手机上的输入流缓冲区中正在接收大量错误的垃圾数据。
过程:我编写和/或修改了三段不同的代码的。首先是在我的笔记本电脑上运行的服务器端程序。原始的源代码可以在这里找到:beej.us/guide/bgnet/样例/server.c(感谢Beej提供的源代码!)。我对它进行了修改以删除警告/错误,并为测试目的添加了自己的连续数据输入循环。以下是修改后的代码:
/* 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;
}这是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);
}
}
}
}
}作业和测试:I可以成功地传输一个字符串,但在connection连接中,这之后的一切都是难以理解的垃圾。想先做家庭作业,我想消除服务器端代码。我使用了Beej的客户端代码(beej.us/guide/bgnet/实例/client.c),并对其进行了修改,使其成为一个好的侦听器。我能够在基于PC的TCP连接上向客户端传输几个字符串.我将客户端的输出重定向到一个文件,并在十六进制编辑器下打开它。瞧,我们没有发现任何错误的数据。我用一台连接到802.11b/g路由器的笔记本电脑作为服务器,用硬连线桌面作为客户端进行了测试。我已经消除了硬件问题,以及服务器端的测试代码问题。这一定是我实现Android客户端代码的方式之一。我还尝试了自动的BufferedReader类来完成我的输入,以及用一个InputStreamReader类手动处理输入。在第一个字符串之后,两者都接收相同的垃圾输出。这让我相信它在套接字的输入流中,但是我该如何修复它呢?有人有什么建议吗?
下面是基于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;
} 谢谢你的帮助!莫斯克罗
发布于 2010-12-11 17:12:24
客户端:
您应该使用new String(buffer, 0, numread)创建字符串,因为并不是所有的缓冲区都已填充,因此没有被read()覆盖的现有字符将出现在字符串中。
您还应该检查numread == -1,因为这表明连接正在关闭。
服务器:
sizeof(some_array)返回整个数组的大小(以字节为单位),这意味着服务器每次发送30个字节。其中大部分将为null (\0),这解释了为什么C客户机似乎工作,因为printf假定第一个空字节表示字符串的结束。但是,Java没有,这可能是日志消息中的额外字节以垃圾形式出现的原因。
一种解决办法可能是:
strlen(string) + 1
\n,即客户机中的\n,放弃第二个InputStreamReader,只使用BufferedReader的readLine()方法,该方法读取下一个换行符。
https://stackoverflow.com/questions/4417816
复制相似问题