I am trying to write an app that sends a string to a specified IP address and Port number. The destination already has a server that accepts strings, but for some reason, the app cannot establish a socket with the server, it keeps timing out. I have only written code, so if I have to do something else like port forward on either the client or server end, please let me know.
The goal of this app is to take in a string for an IP address, a string for the Port number, and a String for the message to send to the destination. After pressing the Send button, the app will send the message to the IP and Port number defined, and display a response from the server.
This also will be used in two applications: once between the Android App and a Python server, and other between the Android App and custom hardware. Hopefully there is a solution to fit both cases.
Client Code:
public static class PlaceholderFragment extends Fragment {
TextView recieve;
EditText addressText, portText, messageText;
Button send;
Socket socket = null;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_customize_gateway, container, false);
recieve = (TextView) rootView.findViewById(R.id.textView1);
addressText = (EditText) rootView.findViewById(R.id.editText1);
portText = (EditText) rootView.findViewById(R.id.editText2);
messageText = (EditText) rootView.findViewById(R.id.editText3);
send = (Button) rootView.findViewById(R.id.send);
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
AsyncSend aSend= new AsyncSend(addressText.getText().toString(),Integer.parseInt(portText.getText().toString()), messageText.getText().toString());
aSend.execute();
}
});
return rootView;
}
public class AsyncSend extends AsyncTask<Void, Void, Void> {
String address;
int port;
String message;
String response;
AsyncSend(String addr, int p, String mes) {
address = addr;
port = p;
message = mes;
}
#Override
protected Void doInBackground(Void... params) {
android.os.Debug.waitForDebugger();
Socket socket = null;
try {
System.out.println("Test");
socket = new Socket(address, port);
System.out.println("Test");
DataOutputStream writeOut = new DataOutputStream(socket.getOutputStream());
writeOut.writeUTF(message);
writeOut.flush();
ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream writeIn = socket.getInputStream();
while((bytesRead = writeIn.read(buffer)) != -1) {
writeBuffer.write(buffer,0,bytesRead);
response += writeBuffer.toString("UTF-8");
}
} catch (UnknownHostException e){
e.printStackTrace();
response = "Unknown HostException: " + e.toString();
System.out.println(response);
} catch (IOException e) {
response = "IOException: " + e.toString();
System.out.println(response);
} finally {
if (socket != null) {
recieve.setText(response);
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
recieve.setText(response);
super.onPostExecute(result);
}
}
}
Server Code:
import http.server
import socket
import threading
import socketserver
import pymongo
import smtplib
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
#Connect to database
try:
from pymongo import MongoClient
dbclient = MongoClient()
db = dbclient.WDI_database
print("Database Connected")
except pymongo.errors.ConnectionFailure as e:
print("Database Failed: {}".format(e))
col = db.users
data2 = str(self.request.recv(1024), 'ascii')
print("Server: {}".format(data2));
data = data2.split("||")
username, password, camunits, homunits = data[0], data[1], data[2], data[3]
post = {"user": username,
"pass": password,
"cam": camunits,
"disp": homunits}
col.insert(post)
print(col.count())
cur_thread = threading.current_thread()
response = bytes("{} Received data for: {}".format(cur_thread, username), 'ascii')
self.request.sendall(response)
class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print("Recieved: " + data.decode("utf-8"))
socket.sendto(data.upper(), self.client_address)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "", 5000
tcpserver = ThreadedTCPServer((HOST, PORT-1), ThreadedTCPRequestHandler)
server_thread = threading.Thread(target=tcpserver.serve_forever)
server_thread.daemon = True
server_thread.start()
print("TCP serving at port", PORT-1)
while True:
pass
tcpserver.shutdown()
Using the Socket class is too low-level for your purposes and fraught with potential gotcha's. I suggest using org.apache.http.client.HttpClient instead.
It was probably because I didn't port forward, so my connection got blocked by my router. I opened the port on both the router and Windows.
Related
it's actually my first time asking a question here, and really hoping someone could give solution to my problem.
I've been working on my Design Project, and one of the feature is that it could communicate from ESP8266 NodeMCU to Android, without the NodeMCU connecting to a network. So it's like the Android connecting directly to the Wifi Module, setting up the NodeMCU as both Access Point and WebServer.
I've established a simple communication, but I want it constant and simultaneous, since i'm using this connection to display the reading of the sensor from the NodeMCU to Android. My problem here is that, it won't constantly give the values, it would only give the first data and then nothing.
Here's my Code in Android:
First is the Client Class
public class Client extends AsyncTask<Void, Void, String> {
String dstAddress;
int dstPort;
String response = "";
TextView textResponse;
Socket socket = null;
Client(String addr, int port, TextView textResponse) {
dstAddress = addr;
dstPort = port;
this.textResponse = textResponse;
}
#Override
protected String doInBackground(Void... arg0) {
Log.d("Status_2", "Sample_2");
try {
if(socket == null)
{
socket = new Socket(dstAddress, dstPort);
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(
1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice: inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
} /*finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}*/
//textResponse.setText(response);
return response;
}
#Override
protected void onPostExecute(String result)
{
Log.d("Status_1", "sample");
textResponse.setText(response);
super.onPostExecute(result);
}
}
Here is from the Main Activity
public class MainActivity extends Activity {
TextView response;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonClear, buttonStop;
int check = 0;
public static Client myClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = findViewById(R.id.addressEditText);
editTextPort = findViewById(R.id.portEditText);
buttonConnect = findViewById(R.id.connectButton);
buttonClear = findViewById(R.id.clearButton);
buttonStop = findViewById(R.id.buttonStop);
response = findViewById(R.id.responseTextView);
myClient = new Client(editTextAddress.getText()
.toString(), Integer.parseInt(editTextPort
.getText().toString()), response);
buttonStop.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
check = 0;
}
});
buttonConnect.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
check = 1;
myClient.execute();
}
});
buttonClear.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
response.setText("");
}
});
}
}
And here is the code from the Arduino:
int status = WL_IDLE_STATUS;
boolean alreadyConnected = false; // whether or not the client was connected
previously
WiFiServer server(8080);
void setup()
{
delay(1000);
Serial.begin(115200);
Serial.println();
// MotionSensor_Setup();
Serial.print("Configuring access point...");
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid,password);
delay(10000);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
Serial.println("\nStarting server...");
// start the server:
server.begin();
}
void loop()
{
// wait for a new client:
WiFiClient client = server.available();
// when the client sends the first byte, say hello:
if(client)
{
if (!alreadyConnected)
{
// clead out the input buffer:
client.flush();
Serial.println(analogRead(A0));
Serial.println();
client.println("Hello, client!");
client.println(analogRead(A0));
delay(500);
alreadyConnected = true;
}
}
if (client.available() > 0) {
// read the bytes incoming from the client:
char thisChar = client.read();
// echo the bytes back to the client:
server.write(thisChar);
// echo the bytes to the server as well:
Serial.write(thisChar);
}
}
Eventually I've tried this code here in the void loop() method.
void loop()
{
// wait for a new client:
WiFiClient client = server.available();
// when the client sends the first byte, say hello:
while(client.connected())
{
client.println(analogRead(A0));
delay(1000);
Serial.println(analogRead(A0));
}
}
it got inside the while condition and displayed data in the Serial Monitor, but didn't displayed in the Android.
I've tried several techniques and still no luck.
I would really appreciate your reply guys, Thank you!
you can try this -> Really simple TCP client
I have doing my android server according this manual and all is work OK
I want to send and receive messages from my socket server which is created in python on windows with the help of twisted API. My client is going to be my android phone through I am going send my string messages. Here is my code. can someone please help out.
public class MainActivity extends AppCompatActivity
{
//TextView textView;
Button sendButton;
Button connect;
EditText message;
OutputStream outputStream;
InputStream inputStream;
Socket socket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendButton = (Button) findViewById(R.id.sendButton);
connect = (Button) findViewById(R.id.button);
message = (EditText) findViewById(R.id.message);
connect.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
connect.setText("Disconnect");
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects)
{
try {
socket = new Socket("192.168.100.106",8888);
try {
outputStream = socket.getOutputStream();
inputStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
connect.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
sendButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view)
{
PrintWriter out = new PrintWriter(outputStream);
String mes = message.getText().toString();
out.print(mes);
}
});
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
asyncTask.execute();
}
});
}
}
And here is my socket server script coded in python with the help of twisted API.
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
import ctypes # An included library with Python install.
class DataTransfer(Protocol):
def connectionMade(self):
#self.transport.write("""connected""")
self.factory.clients.append(self)
print "clients are ", self.factory.clients
self.username = ""
self.password = ""
self.auth = False
self.ipaddress = self.transport.getPeer()
print self.ipaddress
def connectionLost(self, reason):
self.factory.clients.remove(self)
print reason
def dataReceived(self, data):
print data
a = data.split(':')
if len(a) > 1:
command = a[0]
content = a[1]
msg = ""
self.message(msg)
def message(self, message):
self.transport.write(message + '\n')
factory = Factory()
factory.protocol = DataTransfer
factory.clients = []
reactor.listenTCP(8888, factory)
print "Server started"
reactor.run()
Presently I am able to communicate (ie. connect and disconnect with the server.) but its just that I am not able to send and receive messages.
Instead of PrintWriter out = new PrintWriter(outputStream); directly use the outputStream and it should work. :)
I wrote a simple UDP transfer between an Android App and Python Server. I know that the system is working because when I try to connect on a local ip address (192.168.X.X), the correct message is sent and recieved. However, this does not work when I try to use a public IP address. Does anyone know why and how I can try to fix this?
I am trying to implement UDP holepunching, having the server act as the target client of the Android one, but I cannot get the 2nd client's UDP packet to the Android one, it never gets picked up on the Android's side. Would having a 2nd machine act as the 2nd client fix this, or is my code incomplete?
Does my provider (T-Mobile) matter for UDP packet communication?
Client (Android):
public class CustomizeGatewayActivity extends ActionBarActivity {
AsyncUDPReceiver aReceive = null;
static TextView recieve = null;
public static class PlaceholderFragment extends Fragment {
EditText addressText, portText, messageText;
Button udpsend, tcpsend;
Socket socket = null;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_customize_gateway, container, false);
recieve = (TextView) rootView.findViewById(R.id.textView1);
addressText = (EditText) rootView.findViewById(R.id.editText1);
messageText = (EditText) rootView.findViewById(R.id.editText3);
udpsend = (Button) rootView.findViewById(R.id.UDP);
udpsend.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
AsyncUDPSend aSend = new AsyncUDPSend(addressText.getText().toString(), messageText.getText().toString());
aSend.execute();
}
});
public class AsyncUDPSend extends AsyncTask<Void, Void, Void> {
String address = "";
String message = "";
String response = "";
AsyncUDPSend(String addr, String mes) {
address = addr;
message = mes;
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
DatagramSocket dsocket = null;
try {
dsocket = new DatagramSocket();
dsocket.setSoTimeout(10000);
InetAddress dest = InetAddress.getByName(address);
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), dest, 5001);
dsocket.send(packet);
System.out.println("Sent");
byte[] resp = new byte[1024];
DatagramPacket recv = new DatagramPacket(resp, resp.length);
System.out.println("Waitng for Response");
dsocket.receive(recv);
System.out.println("Received");
response = new String(recv.getData());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
System.out.println(response);
} finally {
if (dsocket != null) {
dsocket.close();
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
recieve.setText(response);
super.onPostExecute(result);
}
}
#Override
protected void onResume() {
super.onResume();
aReceive = new AsyncUDPReceiver();
aReceive.start();
}
#Override
protected void onPause() {
super.onPause();
aReceive.kill();
}
public class AsyncUDPReceiver extends Thread {
boolean keepRunning = true;
String response = "";
Runnable updateText = new Runnable(){
public void run() {
if(aReceive == null && recieve == null)
return;
recieve.setText(response);
}
};
public void run() {
android.os.Debug.waitForDebugger();
System.out.println("running");
DatagramSocket dsock = null;
byte[] message = new byte[1024];
DatagramPacket dpack = new DatagramPacket(message, message.length);
try {
dsock = new DatagramSocket(5002);
System.out.println(dsock.toString());
while(keepRunning) {
dsock.receive(dpack);
response = new String(dpack.getData());
System.out.println(response);
runOnUiThread(updateText);
}
} catch (SocketException e) {
// TODO Auto-generated catch block
response = "SocketException: " + e.toString();
System.out.println(response);
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
response = "IOException: " + e.toString();
System.out.println(response);
e.printStackTrace();
} finally {
if(dsock != null)
dsock.close();
}
}
public void kill() {
keepRunning = false;
}
}
}
Server (Python):
class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0].strip().decode("utf-8")
print("{} Recieved: ".format(self.client_address) + data)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
response = data.upper()
sock.sendto(bytes(response, "utf-8"), self.client_address)
print("{} Sent: {}".format(self.client_address,response))
class ThreadedUDPServer(socketserver.ThreadingMixIn, socketserver.UDPServer):
pass
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "", 5000
udpserver = ThreadedUDPServer((HOST,PORT+1), ThreadedUDPRequestHandler)
udp_thread = threading.Thread(target=udpserver.serve_forever)
udp_thread.daemon = True
udp_thread.start()
print("UDP serving at port", PORT+1)
while True:
pass
udpserver.shutdown()
Are you supplying the expected value to InetAddress.getByName(address);
Also since you are trying to do something in background,it will be better if you run a service with wake lock so that you eliminate errors caused due to killing of process.
I am sending a String from an Android device to a python server via TCP socket, but when the message arrives on the server, there are extra characters in the front. For example, if I send the string
asdf
the result on the server would be
\x00\x13asdf
Anyone know why these characters are added to the front of the string? Is there a way to avoid this, or should I just cut these out at the server end?
For the reverse, the server sends
fdsa
The Android client receives
Nullfdsa
Client Code (Written in Android, Java):
public static class PlaceholderFragment extends Fragment {
TextView recieve;
EditText addressText, portText, messageText;
Button send, test;
Socket socket = null;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_customize_gateway, container, false);
recieve = (TextView) rootView.findViewById(R.id.textView1);
addressText = (EditText) rootView.findViewById(R.id.editText1);
portText = (EditText) rootView.findViewById(R.id.editText2);
messageText = (EditText) rootView.findViewById(R.id.editText3);
send = (Button) rootView.findViewById(R.id.send);
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
AsyncTCPSend tcpSend= new AsyncTCPSend(addressText.getText().toString(),Integer.parseInt(portText.getText().toString()), messageText.getText().toString());
tcpSend.execute();
}
});
return rootView;
}
public class AsyncTCPSend extends AsyncTask<Void, Void, Void> {
String address;
int port;
String message;
String response;
AsyncTCPSend(String addr, int p, String mes) {
address = addr;
port = p;
message = mes;
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 4999);
DataOutputStream writeOut = new DataOutputStream(socket.getOutputStream());
writeOut.writeUTF(message);
writeOut.flush();
ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream writeIn = socket.getInputStream();
while((bytesRead = writeIn.read(buffer)) != -1) {
writeBuffer.write(buffer,0,bytesRead);
response += writeBuffer.toString("UTF-8");
}
response = response.substring(4); //Server sends extra "Null" string in front of data. This cuts it out
} catch (UnknownHostException e){
e.printStackTrace();
response = "Unknown HostException: " + e.toString();
System.out.println(response);
} catch (IOException e) {
response = "IOException: " + e.toString();
System.out.println(response);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
recieve.setText(response);
super.onPostExecute(result);
}
}
Server Code (In Python):
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
#Connect to database
try:
from pymongo import MongoClient
dbclient = MongoClient()
db = dbclient.WDI_database
print("Database Connected")
except pymongo.errors.ConnectionFailure as e:
print("Database Failed: {}".format(e))
col = db.users
data2 = str(self.request.recv(1024), 'utf-8')
print("Server: {}".format(data2));
data = data2.split("||")
try:
#[2:] because we get two extra symbols in front of the username from Android
username = data[0][2:]
except IndexError:
username = ""
try:
password = data[1]
except IndexError:
password = ""
try:
camunits = data[2]
except IndexError:
camunits = 0
try:
homunits = data[3]
except IndexError:
homunits = 0
post = {"user": username,
"pass": password,
"cam": camunits,
"disp": homunits}
col.insert(post)
print(col.count())
response = bytes("Received data for: {}".format(username), 'utf-8')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "", 5000
tcpserver = ThreadedTCPServer((HOST, PORT-1), ThreadedTCPRequestHandler)
server_thread = threading.Thread(target=tcpserver.serve_forever)
server_thread.daemon = True
server_thread.start()
print("TCP serving at port", PORT-1)
while True:
pass
tcpserver.shutdown()
I think I got some explanations about the extra characters.
In the java code, you are not getting an extra "Null" from the socket, the response string variable is not initialized, by default it is null, and you say response += writeBuffer.toString("UTF-8"); so you append something to a null string, which happened to be "null" + something.
I would initialize the variable in the declaration or just before the while loop:
String response = "";
In the Phyton code, I see nothing wrong, therefore I'd suggest you to write what you send to the Log and see if the extra characters are in the bytes you send.
Instead of writeOut.writeUTF(message);
try socket.getOutputStream().write(message.getBytes()); // UTF-8 is the default.
and write it to the Log:
android.util.Log.w("SENT", String.format("[%s] %d", message, message.length()));See the log to find out what you're really sending.
Let java send the extra character. It did in my case too.
I used -
data2 = data.strip()
if data2 == "(your desired data)"
//execution instructions
and so on.
i'm new in Android. I have the following code:
public class SettingsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tcp_settings);
Button buttonConnect = (Button) findViewById(R.id.buttonConnect);
buttonConnect.setOnClickListener(new View.OnClickListener() {
EditText server_ip = (EditText) findViewById(R.id.set_server_ip);
EditText port = (EditText) findViewById(R.id.set_port);
#Override
public void onClick(View view) {
String serverAddr = server_ip.getText().toString();
String serverPort = port.getText().toString();
new connectTask().execute(serverAddr, serverPort);
}
});
}
class connectTask extends AsyncTask<String, Void, String> {
Socket socket;
#Override
protected String doInBackground(String... params) {
int servport = Integer.parseInt(params[1]);
try {
socket = new Socket(params[0], servport);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return params[0] + " : " + params[1];
}
}
}
I want to set a socket with server ip and port getting from EditTexts server_ip and port. In the connectTask I make a conversion from string to int in: int servport but i'm still getting error:
Caused by: java.lang.NumberFormatException: Invalid int "".
i have to make serverAddr to String because i have to put it in :
new connectTask().execute(serverAddr, serverPort);
But then socket require port as Int so conversion is required.
Could You help me and tell what i'm doing wrong ?
Your problem lies here within your code. You are passing in multiple parameters into a function that only receives one. Here is the def of execute: execute (Params... params)
new connectTask().execute(serverAddr, serverPort);
Change line to this:
new connectTask().execute(new String[]{serverAddr,serverPort});
Although the documentation does not say it, it is wanting an array of the first template object being passed in IF you are passing in more than one parameter.