How to get connection with ServerSocket? - android

I want to develop app that connect to a server and send and receive message. i'm really beginner in that.
So,i wrote this code by This tutorial, and it seem that i get some mistake with the port or ip address beacuse i didn't get the message to the console. My inspiration is the problem is in my router setting maybe
Here is my android code (Project android)
public class MainActivity extends Activity {
Socket client;
PrintWriter printWriter;
EditText edIp,edPort,edMess;
String message;
int port = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edIp = (EditText) findViewById(R.id.edIp);
edPort = (EditText) findViewById(R.id.edPort);
edMess= (EditText) findViewById(R.id.edMessage);
edIp.setText("10.0.2.2");
edPort.setText("4444");
}
public void onClick(View v){
message = edMess.getText().toString();
edMess.setText("");
port = Integer.parseInt(edPort.getText().toString());
new Thread(new Runnable() {
#Override
public void run() {
try {
client = new Socket(edIp.getText().toString(),port);
printWriter = new PrintWriter(client.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}).start();
}
}
(java aplication)
public class Main {
public static void main(String[] args) throws IOException {
Socket clientSocket = null;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
System.out.println("Server started...");
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("error" + e);
}
Scanner in1 = new Scanner(clientSocket.getInputStream());
String mess;
while (true) {
if(in1.hasNext()){
mess = in1.nextLine();
System.out.println("Client message : "+mess);
}
}
}
}

Related

Using AsyncTask to send a single UDP packet

I am running a python server in my computer that is looping forever and waits for data to be received and when it receives the data, it turns on\off the lights in my room.
In order to control it nicely I created an app that sends UDP packets to the server when I press a button to toggle the lights. My code is:
public class MainActivity extends AppCompatActivity {
private TextView txtView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = findViewById(R.id.status);
new Client(this).execute("init");
}
public void toggle(View view) {
new Client(this).execute("toggle");
}
private static class Client extends AsyncTask<String, String, String> {
DatagramSocket clientSocket;
String address = "192.168.1.243";
int port = 6789;
private WeakReference<MainActivity> activityReference;
Client(MainActivity context) {
activityReference = new WeakReference<>(context);
}
#Override
protected String doInBackground(String... strings) {
try {
clientSocket = new DatagramSocket();
byte[] sendData = strings[0].getBytes();
publishProgress("waiting for data");
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName(address), port);
clientSocket.send(sendPacket);
if (strings[0].equals("init")) {
// Receive result
DatagramSocket serverSocket = new DatagramSocket(6789);
byte[] receiveData = new byte[0];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
publishProgress(new String(receivePacket.getData(), 0, receivePacket.getLength()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (clientSocket != null)
clientSocket.close();
}
return address;
}
#Override
protected void onProgressUpdate(String... strings) {
super.onProgressUpdate(strings);
activityReference.get().txtView.setText(strings[0]);
}
}
}
However, this way, I create a AsyncTask every time I press the button, I wanted to know if it is a good practice or there is a better way to achieve this.
Thanks.
Yes, it's perfectly fine to create a new instance of the AsyncTask. You can not re-run it anyways.

Android Socket client unable to send and receive messages

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. :)

UDP holepunching: PC-to-Android UDP connection does not work with nonlocal addresses

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.

Android networking does not work in emulator

I am working on a basic client-server application to send messages between an android app (client) and a java server on the pc. The messages are being sent and received fine when I use the emulator but does not work when i try to use the app on my mobile. I connect my phone to a wifi network hosted by my laptop using connectify. I wonder whats preventing my phone from connecting...
Here is the code :
SERVER
public class ServerMain {
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
int sock = 1234;
ServerSocket welcomeSocket = new ServerSocket(sock);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
if(clientSentence.equalsIgnoreCase("QUIT"))
break;
}
welcomeSocket.close();
}
}
CLIENT
public class Message extends Activity {
EditText et;
String msg1 = "";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
et = (EditText)findViewById(R.id.etTest);
}
// TODO Auto-generated method stub
class GetMessages extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
final String msg = et.getText().toString();
try{
Socket clientSocket = new Socket("*myip*", 1234);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
String sentence = msg;
outToServer.writeBytes(sentence + '\n');
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public void readWebpage(View view) { //The button on click calls this function (from xml)
new GetMessages().execute();
}
}

Send input to all clients SocketServer Android

I am trying to make a Server that sends back to all connected clients any input it has received. I am using a Service that on create it starts a thread.
public void onCreate()
{
Thread fst = new Thread(new ServerThread());
fst.start();
}
Here is the Thread
public void run()
{
try
{
serverSocket = new ServerSocket(SERVERPORT);
while (true)
{
// listen for incoming clients
Socket client = serverSocket.accept();
mclients = new Vector<Socket>();
mclients.add(client);
boolean finished = false;
try
{
for(int i=0; i<mclients.size(); i++) {
DataInputStream in = new DataInputStream(mclients.get(i).getInputStream());
PrintStream out = new PrintStream(mclients.get(i).getOutputStream());
// Print a message:
System.out.println("Client from : " + mclients.get(i).getInetAddress() + " port " + mclients.get(i).getPort());
// now get the input from the socket...
while(!finished)
{
String st = in.readLine();
// Send the same back to client
out.println(st);
// Write it to the screen as well
System.out.println(st);
// If the input was "quit" then exit...
if (st.equals("quit")) { finished = true; System.out.println("Thread exiting..."); }
}
}
handler.post(new Runnable() {#Override public void run() {}});
}
catch (final Exception e) {handler.post(new Runnable() {#Override public void run() {}});e.printStackTrace();}
}
It works only for the client who sent the input. The input is not echoed back to all clients.Can anyone help me out with this.I think that my client code is wrong but i can't figured it out.Here is my client code:
public class Client extends Activity implements OnClickListener{
private EditText serverIp;
private static EditText data;
private TextView receivedata, answer1 ,answer2, answer3, answer4;
private Button connectPhones, send;
private String serverIpAddress = "";
private boolean connected = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client);
serverIp = (EditText) findViewById(R.id.server_ip);
receivedata = (TextView) findViewById(R.id.textView1);
answer1 = (TextView) findViewById(R.id.txtans1);
answer2 = (TextView) findViewById(R.id.txtans2);
answer3 = (TextView) findViewById(R.id.txtans3);
answer4 = (TextView) findViewById(R.id.txtans4);
data = (EditText) findViewById(R.id.data);
connectPhones = (Button) findViewById(R.id.connect_phones);
send = (Button) findViewById(R.id.send);
connectPhones.setOnClickListener(this);
send.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v == send)
{
if (!connected)
{
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals(""))
{
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
}
public class ClientThread implements Runnable
{
String line;
String[] answers = new String[5];
final Handler handler = new Handler();
final Runnable updateUI = new Runnable() {
public void run() {
receivedata.setText( line );
//answer1.setText( answers[1] );
//answer2.setText( answers[2] );
//answer3.setText( answers[3] );
//answer4.setText( answers[4] );
}
};
public void run()
{
try
{
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: SENDING...");
Socket socket = new Socket(serverAddr, 5000);
connected = true;
while(connected)
{
try
{
BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
out.println(data.getText());
line = in.readLine(); // read server
System.out.println("Echo: " + line);
handler.post(updateUI);
in.close(); // Close stream
out.close();
}
catch (Exception e)
{
Log.e("ClientActivity", "S: Error", e);
}
connected = false;
}
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e)
{
Log.e("ClientActivity", "C: Error", e);
}
}
}}
-----EDIT------
Should i use a different thread for handling the clients or it would be a problem? And how should i do that?
I see that you are also instantiating ServerSocket itself within the loop.
you dont need to create a new serversocket for each connection, you only need one server socket then loop to accept connections and add connections to the (already instantiated in oncreate()) list. see the example below.
if this still doesn't work then we'll have to see rest of the code aswell.
And i like to stress again on that this will not always work on android, as android can also kill your service and app to grab resources, and everytime wifi, 3g or whatever is on the phone looses connection your socket is likely to fail.
ArrayList<Socket> mCLients;
ServerSocket serverSocket;
public void onCreate()
{
mCLients; = new ArrayList<Socke>();
serverSocket = new ServerSocket(SERVERPORT);
Thread fst = new Thread(new ServerThread());
fst.start();
}
//.....
private Static void send(final String message){
Thread thread = new Thread(){
for(Socket socket: mClients){
// send message to the socket
}
}
thread.start();
}
//....
public void run(){
while (true)
{
// listen for incoming clients
Socket client = serverSocket.accept();
mclients.add(client);
//Read client input
MyService.send(message);
}
}
Note this code is no way the best way, i am just giving you a quick example on how you should approach this.
By having a quick (very quick) look i believe your problem seems to be the following code inside the run()
mclients = new Vector();
you are creating a new vector object every-time your program runs.
i suggest to move this out of the run(), and make sure your mClients is created before you start the thread that listens for incoming connections.
However note: running server on the android phone is a bad idea! mobile phones have limitations such as limited battery life, processing, memory and inconsistent internet connectivity, there are other ways to handle such communication. for example consider messaging, c2dm, xmpp etc.

Categories

Resources