I've been trying to implement a simple socket communication between two Android emulators but just can't seem to get it.
My server:
public void run() {
if (SERVERIP != null) {
try {
serverStatus.setText("My IP: " + SERVERIP);
serverSocket = new ServerSocket(6798);
serverStatus.setText("ServerSocket Created");
}
catch(Exception e) {
e.printStackTrace();
}
try {
while (true) {
serverStatus.setText("waiting for client");
Socket client = serverSocket.accept();
serverStatus.setText("Connected.");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = in.readLine();
serverStatus.setText(line);
in.close();
client.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
else
serverStatus.setText("Couldn't detect internet connection.");
}
My Client:
try {
InetAddress ina = InetAddress.getByName("10.0.2.2");
socket = new Socket(ina, 6789);
}
catch (Exception e) {
e.printStackTrace();
}
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Hey Server!");
dispText.setText("sent");
}
catch (Exception e) {
e.printStackTrace();
}
The Client side goes on to display the message "sent" however the Server does not move beyond "waiting for client" (stuck on the blocking accept()).
I've used telnet on my Windows machine to redirect port 6789 to 6798 on the server emulator's console. I've also tried turning off my firewall and the other suggestions posted on the similar questions asked here. Please help as just can't seem to get it and feel like I'm making a very stupid mistake.
Also, can anyone please tell me how it is possible for the Client to move beyond the Socket creation code line if the Server is still stuck on accept(). Or, does it not matter to the client that the Server isn't responding as long as it is listening on the port??
Android emulators are placed behind a virtual firewall/router by design, and cannot see each other, even when they are on the same network. The "Using Network Redirection", as well as "Interconnecting Emulator Instances" part of Google's doc on the emulator explains how to communicate with an emulator instance.
As for your last question. Use the empty constructor for socket, and then use the connect call with a specified timeout.
I have a server and i am trying to send to all clients a specific input(string). My code is here:
serverSocket = new ServerSocket(SERVERPORT);
while (true)
{
// listen for incoming clients
Socket client = serverSocket.accept();
mClients.add(client);
boolean finished = false;
try
{
for (int i=0; i<mClients.size(); i++)
{
Socket well = mClients.get(i);
DataInputStream in = new DataInputStream(well.getInputStream());
PrintStream out = new PrintStream(well.getOutputStream());
// Print a message:
System.out.println("Client from : " + client.getInetAddress() + " port " + client.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..."); }
}
}
As it seems i am doing something wrong. Anyway i am trying to store all the connected sockets to a vector and then send them the string received by one of them. Is this the right approach?
In the first while(true) statement, only listen for incoming connections and then create a separate thread to handle that client connection.
From there, you could add each outPutStream you create, within each thread, into an global ArrayList. Loop through the arrayList(create a method for this with a String Parameter) and write whatever message you want to within said method.
Check out this Oracle Tutorial on Socket Communication for help
I'm kinda new to android socket programming. My android program simply connects to a server (written in c,executed in the console) and must display the content being sent from the server (something like "hi client"). I have textview's for displaying whether the connection is being established or not and another edittext for sending the client's message to the server. The system is connected via Wi-fi. The server is able to recieve messages from my android client but android client is not displaying the message sent by the server. The code snippet for the reading from server part is:
private TextView MsgFromServer; //defination
// here is the code for the connection and starting new thread etc
final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
handler.post(new Runnable() {
#Override
public void run() {
try {
while((line=in.readLine())!=null){
MsgFromServer.append(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Also I tried doing something like this:
final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
line=in.readLine().toString(); //string type
handler.post(new Runnable() {
#Override
public void run() {
MsgFromServer.setText(line);
}
}
both approaches are not working for me.The message I send from the client to the server reaches there properly whereas the other direction communication is not happening. Also I've tested my C server with a simple C client and the message passing is happening smoothly.
How does the client behave? Is it waiting at in.readLine() ?
Be sure the server sends "Hi client\n" (with the lineend).
in.readLines() only returns when a lineend \n is found.
Is the new Runnable running? If you change the code
a little to
try {
MsgFromServer.append("going to read a line..");
while((line=in.readLine())!=null){
MsgFromServer.append(line);
}
then do you see that?
I'm working on an android app that when a button in the app is pressed, sends a key stroke to a server listing on the PC. Everything is working fine expect for a problem of the output "stuttering" when the button is pressed rapidly. If on the client is press rapidly, the server will "stutter" and sometimes simply become unresponsive. The cod I'm using is extremely simple. To simple?
Server side:
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
keyin = inFromClient.readLine();
robby.translateAndForward(keyin);
}
}
catch (Exception ex)
....
On the client
public class ImageBoundListener implements OnTouchListener {
private ImageView view;
private static PadClient client;
The On Touch Event handler
#Override
public boolean onTouch(View view, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;;
if (client==null)
{
client=new PadClient();
}
if (action==MotionEvent.ACTION_DOWN)
{
client.sender("A");
}
Integer actionCode = action & MotionEvent.ACTION_MASK;
Log.d(actionCode.toString()," Event occured on: "+view.getTag());
return true;
}
}
The Actual send implementation
try{
Socket clientSocket = new Socket("192.168.1.104", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Writing bytes to the server..");
outToServer.writeBytes(send);
clientSocket.close();
}
Not sure where to go from here...
There are several issues with your code:
Your code is opening connection every time button is pressed. If it is pressed rapidly - a lot of connections will be opened simultaneously between client and server.
It would be better to make one persistent connection and send all the data through it.
Also you can add some sort of buffering on the client side. I mean that data from several button presses will be combined into one data packet and sent to the server.
When dealing with communication problems between client and server - network I/O logging (what was sent and what was received on either side) is very important.
You server side can look like this:
try {
ServerSocket welcomeSocket = new ServerSocket(6789);
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
while(true) {
keyin = inFromClient.readLine();
Log.d("SERVER"," received: '" + keyin + "'");
robby.translateAndForward(keyin);
}
}
catch (Exception ex) {}
I have two Android devices which I want to connect, using Bluetooth, and transfer data over an RFCOMM channel. I only one one device to receive data, while the other device sends it...
Using this code, I am able to connect to the other device and begin listening to an RFCOMM channel:
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(device, 2);
socket.connect();
class BasicThread implements Runnable{
public void run() {
try {
InputStream stream = socket.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(stream));
while (true){
Log.d("myapp", "now listening...");
latestLine = r.readLine();
Log.d("myapp", latestLine);
}
} catch (IOException e) {
}
}
}
new Thread(new BasicThread()).run();
Using the other device, I have implemented a listening socket like this:
Method m = blue.getClass().getMethod("listenUsingRfcommOn", new Class[] { int.class });
BluetoothServerSocket socket = (BluetoothServerSocket) m.invoke(blue, 2);
BluetoothSocket sock = socket.accept();
Log.d("myapp", "Connected...\n\n\n\n\n\n\n\n");
OutputStream s = sock.getOutputStream();
final PrintWriter out = new PrintWriter(s);
They both connect on RFCOMM channel 2, and both SEE eachother, however, the second device always remains blocked at the BluetoothSocket sock = socket.accept();
Any help?
OK, I am newbie, but I can try to help. So here is my experience, I managed to connect two devices using reflection. My Android phone is receiving data using method listenUsingInsecureRfcommOn, while other devices are masters in communication and send the data over BT SPP. I had a problem with this method since it makes no visible SDP record, so I could not detect it with other devices. Because of that, I made small sniffer using Bluecove and Java SE that tries to connect to every port in given range. Here's the code:
package application.test;
import static java.lang.System.out;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
public class RfCommClient {
public static void main(String args[]) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
String add = "btspp://8C71F894A36D:";
String par = ";authenticate=false;encrypt=false;master=true";
String url = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd;HH-mm-ss-SSS");
for (int i = 1; i < 15; ++i) {
try {
url = add + i + par;
out.format("Time: %s, port = %d\n", sdf.format(System.currentTimeMillis()), i);
StreamConnection conn = (StreamConnection) Connector.open(url);
PrintStream ops = new PrintStream(conn.openOutputStream());
ops.println("Hi there...");
// response
Thread.sleep(1000);
InputStream is = conn.openInputStream();
byte[] resp = new byte[5];
int r = is.read(resp);
out.println("r = " + r + ", response = " + new String(resp, "US-ASCII"));
Thread.sleep(10 * 1000);
conn.close();
} catch (Exception e) {
out.println("Exception occured, time = " + sdf.format(System.currentTimeMillis()) + ", i = " + i);
//e.printStackTrace();
}
}
}
}
What I've learned it that some ports are taken, and that some ports can not be uses (as documentation says, e.g. port 0). For example, port 2 I believe was taken, because when I send some data to it I receive 5 chars back beginning with ERR :).
While, on the other hand, my thread is still waiting?! :)
That leads us to another thing I noticed, ports (or channels) are not always mapped to desired number. For example, to me often happened that I want to send something on port 15, but on Android, thread waiting on port 9 received the data :)
So I suggest, check which port is really allocated!
You can achieve that using the code I posted.
And another thing, here is a link to channelPicker function, which selects channel when ordinary API is used, if I am not mistaken, inside some constants should represent reserved channels.
I just noticed something, my code for registering port is slightly different, here is how I do it:
Method m = cba.getDeclaredMethod("listenUsingInsecureRfcommOn", int.class);
ss = (BluetoothServerSocket) m.invoke(BluetoothAdapter.getDefaultAdapter(), port);
Anyway, I know that this is probably too late, but, maybe someone in future has similar question.