Threading with simple client/serverTCP connection - java

I'm having issues with implementing simple TCP client-server connection in Java, android studio. Networking operations can't run on mainUI thread, asynctask is deprecated, so I'm trying to use Threading. I created client socket in MainActivity and then want it to connect to the server:
client= new ClientTCP();
Log.d("MSG", "Trying to start...");
client.startConnection("xxxxxxxxxxx",8888);
It works well. Now I would like to do more operations such as send a message but I can't just create another Thread for it. At the current state, MainActivity doesn't see client socket as initialized becaused of the threading in Connect() function. It's only working in that particular thread.
What should I do now to make both the Connect and sendMsg (and possibly other networking functions) work on the same thread so they are all initialized and seen in ActivityMain? Right now, this:
client.sendMessage("Im gonna crash.");
crashes the app.
public class Client
{
private Socket clientSocket;
private PrintWriter out;
public void Connect(String ip, int port)
{
new Thread(new Runnable() {
#Override
public void run() {
try {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
Log.d("MSG", "Started Connection!");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
public void sendMessage (String msg){
new Thread(new Runnable() {
#Override
public void run() {
while(clientSocket.isConnected()) {
out.println(msg+"\n");
}
}
}).start();
}
public void stopConnection() {
try {
out.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks.

Related

Android keep socket connection open on thread

thank you for your help.
I'm trying to stream sensor data from my android device to a server via TCP socket. I'm fairly new to Android and threads are a tough concept for me to grasp.
I have two methods, connectToServer() and sendDataToServer(). connectToServer() is called once at startup and sendDataToSever() is called over and over again at about 100 HZ. I would like to open the socket at connectToServer() and leave it open always, so that sendDataToServer() can send data on that socket repeatedly.
public static void connectToServer(){
sendThread = new Thread(new Runnable() {
public void run() {
mySocket = null;
os = null;
try {
mySocket = new Socket(PC_IP, PORT);
os = new DataOutputStream(mySocket.getOutputStream());
} catch (UnknownHostException exception) {
Log.d("sunnyDay", exception.getMessage());
} catch (IOException exception) {
Log.d("sunnyDay", exception.getMessage());
}
}
});
sendThread.start();
}
public static void sendDataToServer(byte[] data) {
String dataString = Arrays.toString(data);
// send this String to the server
sendThread = new Thread(new Runnable() {
public void run() {
if (mySocket != null && os != null) {
try {
os.writeBytes(dataString + "\n");
} catch (IOException exception) {
Log.d("sunnyDay", exception.getMessage());
}
}
}
});
sendThread.start();
}
The only way I've been able to repeatedly send data is by closing and reopening the socket every time in the same thread call, although I feel like this is not the solution.
I tried to have them both on the same thread so that the socket connection is still there, I'm assuming this is where I'm missing something about threads.
Any input is greatly appreciated.
Thanks!
os.flush() after os.writeBytes(dataString + "\n");

TCP Android Server and C# Client

I am trying to create an Android Server and Client on C# base on TCP Socket. I want them both to send and received a string(Data) so I can make a command base on the given string(Data). For the meantime, the Server can listen to incoming clients and the Clients can connect to Server. But I have two problem and i can't solve it.
PROBLEMS:
1. When i try to send the data to Server, the Server was unable to Read it.
2. When the Client is Disconnected, the Server is giving me a loop of Null.
I already try to Search about communicating C# and Android using TCP but i didn't found anything like what i need.
The following code is for Android Server.
I am having a loop of Null in class CommunicationThread when the client is Disconnected. I think it's because I am using a while for reading the Data from client, but since it become disconnected then it is resulting a null.
public class MainActivity extends AppCompatActivity {
TextView tx1, tx_waiting;
private ServerSocket serverSocket;
Handler updateConversationHandler, dg;
Thread serverThread = null;
public static final int SERVERPORT = 6000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tx1 = (TextView)findViewById(R.id.textView1);
tx_waiting = (TextView)findViewById(R.id.tx_waiting);
//Start the Server
try{
updateConversationHandler = new Handler();
dg = new Handler();
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
tx_waiting.setVisibility(View.VISIBLE);
Log.d("Server Starting","Server Already Started.");
}catch (Exception e){
e.printStackTrace();
}
}
#Override
protected void onStop() {
super.onStop();
try {
serverSocket.close();
Log.d("Server Stop","Successfully Stopped the Server Without any Error.");
} catch (IOException e) {
Log.e("Server Failed to Stop",e.toString());
}
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
Log.d("Server Thread","Server Thread Already Started.");
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
Log.d("Server Socket","New Client is Connected");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
Log.d("Input Stream","Input Stream Received!.");
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
Log.d("Update Convers.","Conversation was Updating...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class updateUIThread implements Runnable {
private String msg;
public updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
Log.d("Client Data",msg.toString());
}
}
}
The following code is for C# Client to Connect and Send the Data.
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
Task f = Task.Factory.StartNew(() => {
//Connect the Client into Server
try {
clientSocket.Connect(tb_ip.Text, int.Parse(tb_port.Text));
}
catch (Exception ezz) {
MessageBox.Show("Server Not Found.");
}
//Assuming that the CLient is Connected then Send a Sample Data
try {
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("This is Sample Data");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
}
catch (Exception er) {
Console.WriteLine(er.ToString());
}
});
I have no method yet for Sending the Data from Server to Client since I am just starting to make this thing works, But if you have anything that can help me about this then i will really appreciate it. Thanks.

How to create and maintain a persistent socket connection in Android WiFiDirect?

I'm using WiFiDirect to connect two phones and transfer images between them. I'm able to connect the devices and transfer 1 image from client to server. I'm failing when I try to transfer more than 1 image.
I use onConnectionInfoAvailable method to launch my server and client threads.
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
Log.i(TAG, "GO address " + info.groupOwnerAddress.getHostAddress() + " isGroupOwner " + info.isGroupOwner);
this.info = info;
if (info.groupFormed && info.isGroupOwner) {
ServerRunnable serverRunnable = new ServerRunnable(imageToBeSet);
Thread serverThread = new Thread(serverRunnable);
serverThread.start();
} else {
//Start client thread and transfer image.
}
ServerRunnable :
public class ServerRunnable implements Runnable {
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
Socket clientSocket = serverSocket.accept();
while (connected) {
try {
InputStream inputStream = clientSocket.getInputStream();
final byte[] result = streamToByteArray(inputStream);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
clientImage.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
//Handle exception
}
}
} catch (Exception e) {
//Handle exception
}
}
}
ClientRunnable :
public class ClientRunnable implements Runnable {
public void run() {
try {
Log.d("ClientActivity", "C: Connecting...");
Thread.sleep(2000l);
socket.bind(null);
socket.connect(new InetSocketAddress(host, PORT), 5000);
while (connected) {
if(outputStream == null) {
try {
outputStream = socket.getOutputStream();
} catch (Exception e) {
// Handle exception
}
}
}
} catch (Exception e) {
// Handle exception
}
}
public void write(byte[] bytes) {
try {
outputStream.write(bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The above write method does not work. The OutputStream is connected to the server socket when I debug I see the info about me server (ip address and post number). Not sure why the write is not being read by my server. The socket shows as connected too.
The first transfer works fine. I have a layout with Previous and Next buttons. When the button is pressed, I want to read the image byte array and transfer that. I'm unable to do this part.
If anyone knows how I can create and maintain a persistent socket connection, or any other way to transfer multiple images from client to server using WiFiDirect please let me know. I based this off of the WiFiDirectDemo in Android SDK samples.
Thanks,
Akash
P.S.: I've also looked at the WiFiP2PDemo which uses a WifiP2pDnsSdService. I'm currently trying to understand how they are keeping the sockets open for continuous chat.

Android Socket Programming, continuous server-client communication (on Button-hit)

So, i have a Android-App(Client) and a Java-program(Server), with a One-time socket communication, whenever the android app connects to my server in a special activity (working fine).
Because my server is embedded in a bigger program (with Swing-components, where the server takes its informations from), i have this (reduced) code here:
//somewhere in my Swing-Application
Server myServer = new Server();
myServer.start();
//...
public class Server extends Thread {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8090);
try {
while (true) {
System.out.println("Server is waiting for connections...");
socket = serverSocket.accept();
startHandler(socket);
}
} finally {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void startHandler(final Socket socket) throws IOException {
System.out.println("Client connected to Server");
Thread thread = new Thread() {
#Override
public void run() {
try {
writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
//doing something usefull, i am sending a JSON-String, which i´ll parse in my app.
writer.write(someStringContainingJSONString);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeSocket();
}
}
private void closeSocket() {
try {
socket.close();
} catch (IOException e) {
}
}
};
thread.start();
}
In my Android-App i have:
public void onCreate(Bundle savedInstanceState) {
viewJSON = new Runnable() {
#Override
public void run() {
getJSON();
}
};
Thread thread = new Thread(null, viewJSON, "MagentoBackground");
thread.start();
myProgressDialog = ProgressDialog.show(myActivity.this, "Please wait...", "Retrieving data ...", true);
}
private void getJSON() {
try {
socket = new Socket(serverIPAddress, SERVER_PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String help = reader.readLine();
// parse this String according to JSON, is working fine!
}
// catch and so on...
Now, i want the app, to recieve data, whenever i hit a button "send data" from my Swing-Application, to have the newest data available.
On the other hand, i want the server to recieve data (also a JSON-String) when i make changes in my Android app. The String should also be send when i hit a specific button.
How can i do that? The problem is the threading issue(otherwise my swing application wouldn´t work) combined with networking. If i don´t close the socket, i cannot continue with my program properly (or at least, it seems so with my code right now)
Can you help me out here?
Thank you very much in advance for your help and thoughts.
Best, Andrea

Sending a message to all clients (Client - Server communication)

So now, I am making a client server app based multithread. In server side, I make a thread for everysingle connection that accepted.
In thread class, I make a method that send a command to client. What i just want is, how to send a parameter to all running client? For simple statement, i just want to make this server send a message to all connected client.
I've been read this post and find sendToAll(String message) method from this link. But when i am try in my code, there is no method like that in ServerSocket .
Okay this is my sample code for server and the thread.
class ServerOne{
ServerSocket server = null;
...
ServerOne(int port){
System.out.println("Starting server on port "+port);
try{
server = new ServerSocket(port);
System.out.println("Server started successfully and now waiting for client");
} catch (IOException e) {
System.out.println("Could not listen on port "+port);
System.exit(-1);
}
}
public void listenSocket(){
while(true){
ClientWorker w;
try{
w = new ClientWorker(server.accept());
Thread t = new Thread(w);
t.start();
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
}
}
}
protected void finalize(){
try{
server.close();
} catch (IOException e) {
System.out.println("Could not close socket");
System.exit(-1);
}
}
}
class ClientWorker implements Runnable{
Socket client;
ClientWorker(Socket client){
this.client = client;
}
public void run(){
...
sendCommand(parameter);
...
}
public void sendCommand(String command){
PrintWriter out = null;
try {
out = new PrintWriter(client.getOutputStream(), true);
out.println(command);
} catch (IOException ex) {}
}
}
Thanks for help :)
The below answer, is not recommended for a full fledged server, as for this you should use Java EE with servlets, web services etc.
This is only intended where a few computers want to connect to perform a specific task, and using simple Java sockets is not a general problem. Think of distributed computing or multi-player gaming.
EDIT: I've - since first post - greatly updated this architecture, now tested and thread-safe. Anybody who needs it may download it here.
Simply use (directly, or by subclassing) Server and Client, start() them, and everything is ready. Read the inline comments for more powerful options.
While communication between clients are fairly complicated, I'll try to simplify it, the most possible.
Here are the points, in the server:
Keeping a list of connected clients.
Defining a thread, for server input.
Defining a queue of the received messages.
A thread polling from the queue, and work with it.
Some utility methods for sending messages.
And for the client:
Defining a thread, for client input.
Defining a queue of the received messages.
A thread polling from the queue, and work with it.
Here's the Server class:
public class Server {
private ArrayList<ConnectionToClient> clientList;
private LinkedBlockingQueue<Object> messages;
private ServerSocket serverSocket;
public Server(int port) {
clientList = new ArrayList<ConnectionToClient>();
messages = new LinkedBlockingQueue<Object>();
serverSocket = new ServerSocket(port);
Thread accept = new Thread() {
public void run(){
while(true){
try{
Socket s = serverSocket.accept();
clientList.add(new ConnectionToClient(s));
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
accept.setDaemon(true);
accept.start();
Thread messageHandling = new Thread() {
public void run(){
while(true){
try{
Object message = messages.take();
// Do some handling here...
System.out.println("Message Received: " + message);
}
catch(InterruptedException e){ }
}
}
};
messageHandling.setDaemon(true);
messageHandling.start();
}
private class ConnectionToClient {
ObjectInputStream in;
ObjectOutputStream out;
Socket socket;
ConnectionToClient(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try{
Object obj = in.readObject();
messages.put(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
read.setDaemon(true); // terminate when main ends
read.start();
}
public void write(Object obj) {
try{
out.writeObject(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
public void sendToOne(int index, Object message)throws IndexOutOfBoundsException {
clientList.get(index).write(message);
}
public void sendToAll(Object message){
for(ConnectionToClient client : clientList)
client.write(message);
}
}
And here for the Client class:
public class Client {
private ConnectionToServer server;
private LinkedBlockingQueue<Object> messages;
private Socket socket;
public Client(String IPAddress, int port) throws IOException{
socket = new Socket(IPAddress, port);
messages = new LinkedBlokingQueue<Object>();
server = new ConnecionToServer(socket);
Thread messageHandling = new Thread() {
public void run(){
while(true){
try{
Object message = messages.take();
// Do some handling here...
System.out.println("Message Received: " + message);
}
catch(InterruptedException e){ }
}
}
};
messageHandling.setDaemon(true);
messageHandling.start();
}
private class ConnectionToServer {
ObjectInputStream in;
ObjectOutputStream out;
Socket socket;
ConnectionToServer(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try{
Object obj = in.readObject();
messages.put(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
read.setDaemon(true);
read.start();
}
private void write(Object obj) {
try{
out.writeObject(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
public void send(Object obj) {
server.write(obj);
}
}
There is no method in server socket to send data or message to all running clinet threads.
Please go through the ServerThread.java program which is calling the sendToAll usng server.
// ... and have the server send it to all clients
server.sendToAll( message );
Check out zeroMQ. There are methods known as "pub sub" or "publish subscribe" that will do what you want. You can also use it to communicate between your threads. It is an amazing library in my opinion. It has java or jzmq bindings along with over 30+ others as well so you should be able to use it in your program.
http://www.zeromq.org/

Categories

Resources