- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我一直在四处寻找,但未能找到解决这个特定问题的方法。如果这是一个新手错误,请原谅我,我刚从学校毕业,所以我正在阅读尽可能多的书籍以了解移动设备编程。
目标:将数据从基于 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
BufferedReader
的 readLine()
方法,该方法读取下一个换行符关于java - 桌面到安卓的WiFi TCP连接传输的垃圾数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4417816/
我想检查 wifi 是否有互联网连接。大多数解决方案/方法(包括 alamofire)仅在设备仅连接到 wifi 时才返回 true,不检查 wifi 是否有互联网连接。 最佳答案 苹果的reacha
是否可以通过 wifi 网络发送一些弹出消息或短信/彩信?如果是如何发送。 我的用例是向连接到我的开放 wifi 网络的设备发送某种弹出窗口。弹出窗口可以是图形广告或任何信息之类的东西。 任何人都可以
假设您对无线路由器有完全的编程控制(运行 OpenWrt 或 DD-WRT - Linux)。路由器配置为广播 ssid,并且网络完全开放。 移动用户(iPhone/Android/BB)走过来。 1
我正在编写一个 Android 应用程序,并试图弄清楚是否有可靠的方法来确定手机何时连接到特定的 wifi 网络。 例如,我只想在连接到家庭 wifi 时执行某些操作。 有人知道这是否可行吗? 最佳答
我想把我的 Raspberry PI 3 变成类似 WiFi 信号放大器、无线中继器/扩展器或 WiFi 热点之类的东西,可以放大微弱的 WiFi 信号。 经过一番研究,我找到了这个教程,点击 her
我目前正在使用我的 mongodb 服务器以及正在运行的 Nodejs 服务器测试我的 Android 应用程序。我希望服务器可以像内联网一样通过 WiFi 访问,以便手机上的应用程序可以访问本地服务
问题陈述 调用pcap_activate()结果 PCAP_ERR_RFMON_NOTSUP错误,即不支持射频监控模式。 上下文 我正在编写小型 C 程序,其工作是在监听模式下监听笔记本电脑的 wif
想象一下这种情况,周围有一些智能手机和计算机,它们的 WiFi 适配器(无线适配器)打开,但没有必要连接到网络。 有没有办法通过 Linux 机器查看 MAC 地址? 任何见解表示赞赏。 最佳答案 断
我在 WiFi 连接检测方面遇到问题。我的目标是检测用户何时在不同的 WiFi 之间切换。我发现this ,但它只检测 WiFi 何时建立。就我而言,我需要知道手机上的一个 WiFi 网络何时更改为另
我想获取一些有关 Wifi 的信息,例如 SSID 名称、IP 地址和速度,所以我编写了这段代码 WifiManager wifiMgr = (WifiManager) getSystemServic
我正在安装一个系统来监控一些传感器,并根据它们打开/关闭几盏灯。 为了进一步的数据分析,我们还想将该数据发送到中央服务器,因此我们添加了 Wifi 屏蔽。 请记住,如果没有网络,系统应该可以正常运行。
这两天我一直在苦苦挣扎,我找不到解决办法。我尝试了这段代码,但随着时间的推移,它在 Android 5(Lollipop) 上运行,但在 7.1.1.(Nougat) 上不起作用。我有另一个场景,手机
我正在开发一些软件来管理通过 ZigBee 与 Remote 通信的设备。我们希望设备能够通过 Wi-Fi 与网络服务器和/或智能手机通信,以便我们的软件可以与之交互。 ZigBee Remote 很
自 setWifiEnabled在 Android 10 上已弃用,如何在 Android 10 设备上以编程方式启用 wifi? 是否无法在 Android 10+ (SDK 29) 上以编程方式启
我正在尝试从 WiFi 数据包中获取 RSSI 或信号强度。 我还想要来自“WiFi 探测请求”的 RSSI(当有人在搜索 WiFi 热点时)。 我设法从 kismet 日志中看到它,但这只是为了确保
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 此问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-topic
我需要一个 IOS 应用程序,用户将在其中启动应用程序,录制音频语音(通过设备麦克风),该语音语音将广播给同一网络上的其他用户,所有这些都必须通过无线连接(WIFI)进行直播。 我对可能的解决方案进行
更新: 我指出了问题的来源。为了避免任何复杂化,我使用 ScanNetwork 示例,所以我什至不必输入 SSID .该代码在遇到 WiFi.status() 后立即停止在板上运行. 我有一个 Ser
在我的 android 应用程序中,我连接到 WiFi 网络。但是,例如,如果我多次连接到这个网络,这个网络的名称就会多次出现在标准的 android WiFi 列表中。我怎样才能避免这种情况? 我的
我有可用的 wifi 网络列表列表,现在我想连接到特定网络。所以请指导我在 ListView 中获取网络列表后必须做什么。 **package com.example.wifilist imp
我是一名优秀的程序员,十分优秀!