gpt4 book ai didi

java - 桌面到安卓的WiFi TCP连接传输的垃圾数据

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:19:58 24 4
gpt4 key购买 nike

我一直在四处寻找,但未能找到解决这个特定问题的方法。如果这是一个新手错误,请原谅我,我刚从学校毕业,所以我正在阅读尽可能多的书籍以了解移动设备编程。

目标:将数据从基于 PC 的套接字服务器无线传输到基于 Android 的客户端 (802.11 b/g),然后客户端将处理所述数据以输出给用户。

问题:Android 手机的输入流缓冲区中接收到大量错误的垃圾数据。

程序:我已经编写和/或修改了三段不同的代码。首先是在我的笔记本电脑上运行的服务器端程序。原始源代码可以在这里找到:beej.us/guide/bgnet/examples/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);
}
}


}

}
}

家庭作业和测试:我可以成功传输一个字符串,但之后的所有内容在 PC-Android 连接中都是无法理解的垃圾。想先做功课,我想消除服务器端代码。我采用了 Beej 的客户端代码 (beej.us/guide/bgnet/examples/client.c) 并将其修改为只是一个好的倾听者。我能够在基于 PC-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;
}

感谢您的帮助!莫斯科

最佳答案

客户:

您应该使用 new String(buffer, 0, numread) 创建字符串,因为可能并非所有缓冲区都已填充,因此现有字符不会被 read() 将出现在字符串中。

您还应该检查 numread == -1,因为这表明连接已关闭。

服务器:

sizeof(some_array) 返回整个数组的大小(以字节为单位),这意味着您的服务器每次发送 30 个字节。其中大部分将为空 (\0),这解释了为什么 C 客户端似乎可以工作,因为 printf 假定第一个空字节表示字符串的结尾。然而,Java 不会,这可能就是日志消息中额外字节显示为垃圾的原因。

一个解决方案可能是:

  • 修改服务器以发送消息中的确切字符数,包括终止 \n,即 strlen(string) + 1
  • 然后在客户端中,放弃第二个 InputStreamReader,只使用 BufferedReaderreadLine() 方法,该方法读取下一个换行符

关于java - 桌面到安卓的WiFi TCP连接传输的垃圾数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4417816/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com