目前我正在试图从我的Android系统的智能手机将消息发送到一个树莓派。我实现了一个Android客户端通过此处给出的示例代码:
我改变了IP地址的端口,因此它与我的服务器上运行的PI工作。该服务器是用C语言编写,并切换到Android之前,我实现了一个C-Client,它至今工作没有任何问题。
服务器只需要接收消息,然后打印出它并停止,所以它是非常简单的。
编辑3
我创造了新的输出,用于调试和分析,我可以搞到现在的想法是什么是行不通的。据我所看到的,永远不会执行的SendMessageTask
。
服务器输出现在:
成功 - 创建套接字
成功 - 绑定
听力
成功 - 接受
现在它档,“读书......”从不打印! (应在while循环发生)
在Android中我收到以下neccessary输出:
d / TCP客户端:C:连接...
d / TcpOptimizer:TcpOptimizer-ON
- >连接发生
当我按下发送按钮:
d /化MyMessage1:按钮被推
d / myMessage:测试
但我没有得到应在SendMessageTask
被记录的消息
当我点击断开按钮服务器打印:
客户端断开连接
而现在Android的日志:
d / RESPONSE FROM SERVER:S:收到的消息: '空'
d / sendMessageTask:尝试发送邮件
d / TcpClient的:不能发送 - > mBufferOut为null
因此,我的猜测是,该SendMessageTask
从来没有运行,直到它失败,因为断开,但为什么呢?
编辑3 - 完
这是(编辑)服务器代码:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
int main(){
int welcomeSocket, newSocket, read_size;
char buffer[10000];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
if (welcomeSocket == -1) {
printf("Could not create socket\n");
}else {
printf("Success - create socket\n");
}
/*---- Configure settings of the server address struct ----*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = INADDR_ANY;
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
if(bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0){
printf("Error - Binding\n");
}else {
printf("Success - Binding\n");
}
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
if(newSocket < 0){
printf("Error - Accept\n");
}else {
printf("Success - Accept\n");
}
while( (read_size = recv(newSocket, buffer, 10000, 0)) > 0){
write(newSocket, buffer, strlen(buffer));
printf("reading...");
}
if(read_size == 0){
printf("Client disconnected");
fflush(stdout);
}
else if(read_size == -1){
printf("Error - recv failed");
}
return 0;
}
我不太清楚,如果参数
welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
仍然是正确的?
客户码在Android是:
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClient {
public static final String TAG = TcpClient.class.getSimpleName();
public static final String SERVER_IP = "192.168.4.1"; //server IP address
public static final int SERVER_PORT = 7891;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* @param message text entered by client
*/
public void sendMessage(final String message) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (mBufferOut != null) {
Log.d(TAG, "Sending: " + message);
mBufferOut.println(message);
mBufferOut.flush();
}else{
Log.d(TAG, "Cannot send --> mBufferOut is null");
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
/**
* Close the connection and release the members
*/
public void stopClient() {
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
/*
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
*/
}
Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
//class at on AsyncTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
而我(编辑)Mainactivity包括的AsyncTask的连接
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;
public class MyActivity extends AppCompatActivity {
private TextView mTextMessage;
private TextView myAwesomeTextView;
private TcpClient mTcpClient;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
return true;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_myActivity);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
myAwesomeTextView = (TextView)findViewById(R.id.editText);
//TCP connect
new ConnectTask().execute("");
//Buttons
final Button button_Send = findViewById(R.id.button_Send);
button_Send.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Set text (debugging)
myAwesomeTextView.setText("My Awesome Text");
Log.d("myMessage1", "button pushed ");
//sends the message to the server
String message = "testing\0";
//String message = "testing\n\r";
if (mTcpClient != null) {
new SendMessageTask().execute(message);
//not needed just for debugging
Log.d("myMessage", "testing ");
}
}
});
final Button button_Disconnect = findViewById(R.id.button_Disconnect);
button_Disconnect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mTcpClient != null) {
mTcpClient.stopClient();
}
}
});
}
@Override
protected void onPause() {
super.onPause();
if (mTcpClient != null) {
// disconnect
new DisconnectTask().execute();
}
}
/**
* Sends a message using a background task to avoid doing long/network operations on the UI thread
*/
public class SendMessageTask extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params) {
// send the message
mTcpClient.sendMessage(params[0]);
Log.d("sendMessageTask", "try to send message ");
return null;
}
@Override
protected void onPostExecute(Void nothing) {
super.onPostExecute(nothing);
//nothing to do yet
}
}
/**
* Disconnects using a background task to avoid doing long/network operations on the UI thread
*/
public class DisconnectTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
// disconnect
mTcpClient.stopClient();
mTcpClient = null;
return null;
}
@Override
protected void onPostExecute(Void nothing) {
super.onPostExecute(nothing);
//nothing to do yet
}
}
public class ConnectTask extends AsyncTask<String, String, TcpClient> {
@Override
protected TcpClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
@Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
Log.d("test", "response " + values[0]);
//process server response here....
}
}
}
编辑#2(失败的行为仍然存在)
我设法得到了这个工作。
我改了行
new SendMessageTask().execute(message);
至
new SendMessageTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);
这让发工作。
我也改变了服务器的代码如下:
#define MAX 2048
#define PORT 7891
#define SA struct sockaddr
// Function designed for chat between client and server.
void communicate(int sockfd)
{
char buff[MAX];
int n;
// infinite loop for chat
for (;;) {
bzero(buff, MAX);
// read the message from client and copy it in buffer
read(sockfd, buff, sizeof(buff));
// print buffer which contains the client contents
printf("From client: %s\t To client : ", buff);
bzero(buff, MAX);
n = 0;
// copy server message in the buffer
while ((buff[n++] = getchar()) != '\n');
// and send that buffer to client
write(sockfd, buff, sizeof(buff));
// if msg contains "Exit" then server exit and chat ended.
if (strncmp("exit", buff, 4) == 0) {
printf("Server Exit...\n");
break;
}
}
}
// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed..\n");
exit(0);
}
else
printf("Server listening...\n");
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client..\n");
// Function for chatting between client and server
communicate(connfd);
// After chatting close the socket
if(close(sockfd) < 0){
printf("Error - closing socket...\n");
}
else{
printf("Socket successfully closed..\n");
}
}