Send message from client to server - java

I have develop a chat with an Android client made with android studio and a Server made with Java.
How can i do to send a message from the Client to the server? And from the server broadcast the message to all clients?
Example:
Client#1 send:Hello
Server receive:Hello
Server send the message(Hello) to all other Clients.
Main Server:
package server1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
public class Server1 {
public static void main(String[] args) throws IOException {
Socket newsock = null;
int nreq = 1;
try
{
ServerSocket sock = new ServerSocket (3000);
for (;;)
{
newsock = sock.accept();
System.out.println("Creating thread ...");
Thread t = new ThreadHandler(newsock,nreq);
t.start();
}
}
catch (Exception e)
{
System.out.println("IO error " + e);
}
System.out.println("End!");
BufferedReader in=new BufferedReader(new InputStreamReader(newsock.getInputStream()));
PrintWriter out=new PrintWriter(newsock.getOutputStream(),true);
}
}
ThreadHandler (Server):
package server1;
import java.io.*;
import java.net.*;
class ThreadHandler extends Thread {
Socket newsock;
int n;
ThreadHandler(Socket s, int v) {
newsock = s;
n = v;
}
public void run() {
try {
PrintWriter outp = new PrintWriter(newsock.getOutputStream(), true);
BufferedReader inp = new BufferedReader(new InputStreamReader(
newsock.getInputStream()));
outp.println("Hello :: enter QUIT to exit \n");
boolean more_data = true;
String line;
while (more_data) {
line = inp.readLine();
System.out.println("Message '" + line + "' echoed back to
client.");
if (line == null) {
System.out.println("line = null");
more_data = false;
} else {
outp.println("From server: " + line + ". \n");
if (line.trim().equals("QUIT"))
more_data = false;
}
}
newsock.close();
System.out.println("Disconnected from client number: " + n);
} catch (Exception e) {
System.out.println("IO error " + e);
}
}
}
Android MainActivity.java:
package com.example.mirko.chatclient;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
TextView chatzone;
EditText msg;
Button btninvio;
Socket socket;
PrintWriter out;
BufferedReader in;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final int PORTA=3000;
final String IP = "192.168.1.2";
try {
socket=new Socket(IP,PORTA);
} catch (IOException e) {
e.printStackTrace();
}
//si connette al server
chatzone= findViewById(R.id.chatzone);
msg= findViewById(R.id.msg);
btninvio=findViewById(R.id.btninvia);
//si dichiara i componenti
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
try {
out= new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void premuto(View v)
{
String messaggio=msg.getText().toString();
out.println(messaggio);
}
}
Android xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mirko.chatclient.MainActivity">
<TextView
android:id="#+id/chatzone"
android:layout_width="343dp"
android:layout_height="309dp"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:text="#string/chatzone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btninvia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:layout_marginEnd="148dp"
android:onClick="premuto"
android:text="#string/invia"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<EditText
android:id="#+id/msg"
android:layout_width="344dp"
android:layout_height="43dp"
android:layout_marginBottom="32dp"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="32dp"
android:ems="10"
android:inputType="text"
android:labelFor="#+id/msg"
android:text="#string/msg"
app:layout_constraintBottom_toTopOf="#+id/btninvia"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/chatzone" />

Your server code has a logical problem. You launch a new thread for each client connection. Your ThreadHandler reads and writes to that single client. It has no information on any other possible clients.
Your server must have a "main thread" which handles communication between clients. Your client threads each should have a FIFO queue for outbound messages. The server needs to keep a central FIFO queue of incoming messages and a list of pointers to per-client outbound message queues. Client thread reads a message from its socket then puts it to the central incoming queue. The "main thread" reads messages from that queue and places them into outbounds queues of each client thread. All of this has to be properly synchronized.
So, your client thread reads messages from socket and places them into a common queue, then reads messages from its own outbound queue and writes them to socket. The main thread reads messages from the common incoming queue and writes them to outbound queues of indivual client threads.
In general, the problem you are trying to solve is quite hard. Unless this is a purely learning experience for you and it's OK to fail, you should not build your own. Use something off the shelf, like the one suggested earlier or https://github.com/tinode/chat
Besides, Java is not the best language for such servers-side applications. Most such apps are written in Erlang (https://github.com/esl/MongooseIM) and Go.

Related

Running HTTP Request in seperate Thread not working

I have been trying to get some very simple code to work which should read an online file and print the contents of that file in the log. At first I didn't know that it needed to be handled in a seperate thread so I left it in the onCreate Method. Now I put it into a seperate Thread with the help of this question: How to use separate thread to perform http requests but the app still crashes! Since I'm desperate to get this working so I can keep on learning how to program this app, I will insert the exact code I used:
package com.dan6erbond.schoolhelper;
import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private String link = "https://dan6erbond.github.io/I1A/Documents/Zusammenfassungen/Zusammenfassungen.json";
String content;
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
Log.i("TAG", content);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread downloadFile = new Thread(new Runnable(){
#Override
public void run(){
try {
URL url = new URL(link);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
content += str;
}
Log.i("TAG", content);
in.close();
} catch (Exception e) {
Log.i("TAG", "Error occured!");
}
handler.sendEmptyMessage(0);
}
});
downloadFile.start();
}
}
In the log the error message is being sent:
01-05 07:40:33.320 9601-9622/com.dan6erbond.schoolhelper I/TAG: Error occured!
I'd be really happy if someone could help me with this problem. It's probably very simple but I just started coding in Android Studio so I'm really new to this.
I just needed to add the INTERNET permission. I figured that out by printing the error message:
Log.i("TAG", e.getMessage());
Which resulted in this:
01-05 08:05:10.806 11815-11838/com.dan6erbond.schoolhelper I/TAG: Permission denied (missing INTERNET permission?)
I just added this to the Android Manifest:
<uses-permission android:name="android.permission.INTERNET"/>
Thanks everyone for your help!

Buetooth connection failed: read failed, socket might closed or timeout, read ret: -1

I am trying to create a Bluetooth connection.
I can search for nearby devices but when I try to connect I get an error I do not understand:
LOGCAT
01-03 00:55:06.909 6654-6654/com.bluetooth.prova3.listdiscovery D/CONNECTTHREAD: Could not close connection:java.io.IOException: read failed, socket might closed or timeout, read ret: -1
I Have two classes for connect, one that receives the device and execute the connection, an other for make connection.
ConexionActivity.Java
package com.bluetooth.prova3.listdiscovery;
***Imports*****
public class ConexionActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_conexion);
//Aqui rebo el dispositiu que he seleccionat per conectarme
Intent intent = getIntent();
BluetoothDevice bluetoothDevice = intent.getExtras().getParcelable("btdevice");
//mostro el nom per la pantalla amb un text view
TextView MacAddress = (TextView)findViewById(R.id.MAC);
String aaaa = bluetoothDevice.getName() + "\n" + bluetoothDevice.getAddress();
MacAddress.setText(aaaa);
ConnectThread conexion = new ConnectThread(bluetoothDevice);
conexion.run();
}
}
ConnectThread.java
package com.bluetooth.prova3.listdiscovery;
Imports
public class ConnectThread extends Thread{
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
UUID UUIDaleatorio = UUID.randomUUID();
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(UUIDaleatorio);
} catch (IOException e) {
Log.d("CONNECTTHREAD", "Could not close connection:" + e.toString());
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
//mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
Log.d("CONNECTTHREAD", "Could not close connection:" + connectException.toString());
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { Log.d("CONNECTTHREAD", "Could not close connection:" + closeException.toString());}
return;
}
// Do work to manage the connection (in a separate thread)
// manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Try to use ,
createInsecureRfcommSocketToServiceRecord(MY_UUID)
in place of
createRfcommSocketToServiceRecord(MY_UUID)
This should fix the problem. Share your debugging results , if this doesn't fix the issue.
Also , don't generate random UUID(s), try the one below.
UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
This worked for me..
final String PBAP_UUID = "0000112f-0000-1000-8000-00805f9b34fb";
mmSocket=device.createInsecureRfcommSocketToServiceRecord(ParcelUuid.fromString(PBAP_UUID).getUuid());
// mmSocket = device.createRfcommSocketToServiceRecord(uuid);
Log.d("Connection","Created");
try {
mmSocket.connect();
Log.d("Connection","Connected");
}catch (Exception e){
if(mmSocket != null) {
try {
mmSocket.close();
} catch (IOException e1) {
Log.e("Connection","Socket close Error"+e1.getMessage());
}
mmSocket = null;
}
e.printStackTrace();
Log.e("Connection","Genmral Error "+e.getMessage());
}
I tied all solutions in the post, but without success. The error still appeared:
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:772)
at android.bluetooth.BluetoothSocket.waitSocketSignal(BluetoothSocket.java:725)
at android.bluetooth.BluetoothSocket.accept(BluetoothSocket.java:499)
at android.bluetooth.BluetoothServerSocket.accept(BluetoothServerSocket.java:171)
at android.bluetooth.BluetoothServerSocket.accept(BluetoothServerSocket.java:157)
at com.milen.bluetoothapp.services.MyBluetoothService$AcceptThread.run(BluetoothConnectionService.kt:71)
I got success when I changed createInsecureRfcommSocketToServiceRecord(MY_UUID) whit this:
private inner class ConnectThread(device: BluetoothDevice) : Thread() {
private var bluetoothSocket: BluetoothSocket? = device.javaClass.getMethod(
"createRfcommSocket", Int::class.javaPrimitiveType
).invoke(device, 1) as BluetoothSocket?
...
}
Yeah, it is a hacky-reflection way, but it could save someone's life ;).
In Java it would look like this:
BluetoothSocket tmp = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class } ).invoke(device, 1);
By the way, I found the solution in one opensource Github project here
Always check that your device is paired! Failure causes the same error.
BluetoothDevice device = adapter.getRemoteDevice("11:22:33:44:55:66");
if (device.getBondState()!=BluetoothDevice.BOND_BONDED)
{
// Log or Toast
}
I too struggled with this error for a while. Below is what finally works for me (in Kotlin):
MainActivity.kt:
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.content.Intent
import android.os.Bundle
import android.os.ParcelUuid
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val requestCode = 101
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
connectBluetooth()
}
private fun connectBluetooth() {
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if (!bluetoothAdapter.isEnabled) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, requestCode)
}
val pairedDevices = bluetoothAdapter.bondedDevices
if(pairedDevices.isNotEmpty()){
val device: BluetoothDevice = pairedDevices.first()
val connectThread = Thread(ConnectThread(device))
findViewById<TextView>(R.id.textView).text = device.name
findViewById<Button>(R.id.connectBtn).setOnClickListener{ connectThread.run() }
findViewById<Button>(R.id.disconnectBtn).setOnClickListener{ connectThread.run() }
}
}
private inner class ConnectThread(device: BluetoothDevice) : Thread() {
private val uuid: ParcelUuid = ParcelUuid.fromString("0000112f-0000-1000-8000-00805f9b34fb")
private val mmSocket: BluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid.uuid)
override fun run() {
try {
if(mmSocket.isConnected) mmSocket.close() else mmSocket.connect()
Log.d("Bluetooth Activity", "Socket is connected: ${mmSocket.isConnected}")
} catch (ex: Exception) {
Log.e("Bluetooth Activity", ex.toString())
}
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No device connected"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/connectBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="48dp"
android:text="Connect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/textView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.501" />
<Button
android:id="#+id/disconnectBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="64dp"
android:text="Disconnect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/textView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.498" />
</androidx.constraintlayout.widget.ConstraintLayout>

VB.Net Server & Android Client (Socket) Send & Receive

I am new to Android programming I wrote a simple Server(VB.NET) / Client(Java/Android) program. Text from Android/Java is send successfully to VB.Net but Response from VB.Net is not received in Android/Java (buffer.readLine() returns null)
Am I missing something?
Here are my Codes
VB.NET (Server)
Imports System.Net.Sockets
Imports System.Text
Public Class Form1
Dim server As New TcpListener(9999)
Dim client As New TcpClient
Dim stream As NetworkStream
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Start_Click(sender As Object, e As EventArgs) Handles Start.Click
Me.Text = "Waiting...."
Dim str As String
server.Start()
client = server.AcceptTcpClient
stream = client.GetStream()
Dim r_byt(client.ReceiveBufferSize) As Byte
stream.Read(r_byt, 0, client.ReceiveBufferSize)
Str = Encoding.ASCII.GetString(r_byt)
Label1.Text = str
End Sub
Private Sub Responce_Click(sender As Object, e As EventArgs) Handles Responce.Click
Dim s_byt() As Byte = Encoding.ASCII.GetBytes("Got it" & vbCr)
stream.Write(s_byt, 0, s_byt.Length)
stream.Flush()
stream.Close()
client.Close()
server.Stop()
End Sub
Android/Java(Client)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class Main extends Activity {
Button buttonSend, buttonReceive;
private static Socket socket = null;
PrintStream stream = null;
BufferedReader buffer = null;
String string = "a";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonSend = (Button) findViewById(R.id.buttonSend);
buttonSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
try {
socket = new Socket("192.168.0.104", 9999);
stream = new PrintStream(socket.getOutputStream());
stream.println("Hi Server...");
buffer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
string = buffer.readLine();
Log.d("ServerActivity", " - " + string);
buffer.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
It looks like you have a couple of issues:
In the server side, you are trying to read something from the socket
into r_byt, and you are not writing anything to it on cliente side.
When you press the send button on server side, r_byt still null and
that's what you receive on cliente side.
On client side the call to socket read is blocking and after a few
seconds will result in a ANR error (Application not Responding) in
the cliente. You should move the socket read to a different thread
from the UI. The newer Android versions don't even let you read from
a socket in the UI thread.
Regards.

Server/Client Android to PC communication issue

Im trying to write a program using sockets having an android phone as the client and my PC as the server i found and slightly modified code for both sides and my server code works but i can't get the client activity to and i don't know acutally how to get the to programs to talk i want to basically be able to have either side input text and have it sent and set visable to the other i know how much of a stickler you guys are for questions so... How do i get these to communicate?
Client code (The emulator crashes before i can even begin to see the problem)
package com.example.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.*;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.*;
import java.net.*;
public class ClientActivity extends Activity {
private EditText serverIp;
private Button connectPhones;
private String serverIpAddress = "";
private boolean connected = false;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
connectPhones.setOnClickListener((android.view.View.OnClickListener) connectListener);
}
private OnClickListener connectListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (!connected) {
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals("")) {
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
};
public class ClientThread implements Runnable {
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
Socket socket = new Socket(serverAddr, 9999);
connected = true;
while (connected) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true);
// where you issue the commands
out.println("Hey Server!");
Log.d("ClientActivity", "C: Sent.");
} catch (Exception e) {
Log.e("ClientActivity", "S: Error", e);
}
}
socket.close();
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e) {
Log.e("ClientActivity", "C: Error", e);
connected = false;
}
}
}
}
the Server code
import java.io.*;
import java.net.*;
/**
* Simple server using Java Sockets.
* #author Jonathan Engelsma (http://www.cis.gvsu.edu/~engelsma)
*
*/
public class Server {
/**
* #param args
*/
public static void main(String[] args) {
try {
// First we create a server socket and bind it to port 9999.
ServerSocket myServerSocket = new ServerSocket(9999);
// wait for an incoming connection...
System.out.println("Server is waiting for an incoming connection on host="
+ InetAddress.getLocalHost().getCanonicalHostName()
+ " port=" + myServerSocket.getLocalPort());
Socket skt = myServerSocket.accept();
// ok, got a connection. Let's use java.io.* niceties to read and write from the connection.
BufferedReader myInput = new BufferedReader(new InputStreamReader(skt.getInputStream()));
PrintStream myOutput = new PrintStream(skt.getOutputStream());
// attempt to read input from the stream.
String buf = myInput.readLine();
// if we got input, print it out and write a message back to the remote client..
if (buf != null) {
System.out.println("Server read: [" + buf + "]");
myOutput.print("got it");
}
// close the connection.
skt.close();
System.out.println("Server is exiting");
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("Whoops, something bad happened! I'm outta here.");
}
}
}
Are you using
<uses-permission android:name="android.permission.INTERNET" />
In the Android Manifest? That could cause your problem.
if you are using ICS or JB, then you are probably being restricted from opening network connections from within your main activity. you will get an opaque error message regarding network permissions.
i cant repost my answer to another quite similar StackOverflow question here (it is considered spamming by moderators), but you can CHECK IT OUT HERE.
i posted a functional send and receive socket connector client using asynctask there.

SocketChannel is not ready

again i have got a problem with socket programming in Android. My Problem is Selector.select() returns zero that there are no SocketChannels ready for writing. And again the same code works in normal Java but does not work in Android. Here is my code:
package com.test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class WebSocketTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SocketChannel channel = null;
SocketAddress socketAdress = new InetSocketAddress("10.0.0.1", 8787);
try {
channel = SocketChannel.open();
} catch (IOException e) {
Log.e("ERROR", "channel open");
}
try {
channel.configureBlocking(false);
} catch (IOException e1) {
Log.e("ERROR", "channel blocking");
}
try {
channel.connect(socketAdress);
} catch (IOException e) {
Log.e("ERROR", "channel connect");
}
try {
while(!channel.finishConnect())
{
}
} catch (IOException e1) {
Log.e("ERROR", "channel finishConnect");
}
Selector selector = null;
try {
selector = Selector.open();
} catch (IOException e) {
Log.e("ERROR", "selector open");
}
try {
channel.register(selector, channel.validOps());
} catch (ClosedChannelException e) {
Log.e("ERROR", "channel register");
}
boolean i = true;
while(i)
{
int readyChannels = 0;
try {
readyChannels = selector.select();
} catch (IOException e) {
Log.e("ERROR", "selector select");
}
if(readyChannels > 0)
{
i = false;
}
}
}
}
In Java readyChannels = 1. In Android it is 0.
Can anyone help me?
Emulator sits behind a virtual router. You need to configure Network Redirections (port forwarding) to make a certain port on emulator visible to the outside network (including your computer).
There are several issues with this NIO code.
Instead of connecting and then spinning around finishConnect(), possibly forever, you should connect before going into non-blocking mode. At the moment you're just burning the CPU, flattening the battery, etc.
You should only register OP_WRITE when you have something to write. It is normally 'ready', so if you register the channel for it permanently your selection loop will just spin. The only time OP_WRITE isn't ready is when you have filled the socket send buffer.

Categories