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

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

Related

Threading with simple client/serverTCP connection

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.

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.

Reconnecting sockets in Android

Here's the problem. I'm attempting to set up a very simple app that will send messages to a Java server.
Here is my server code:
ServerSocket serverSocket = null;
Socket clientSocket =null;
try
{
serverSocket = new ServerSocket(4444);
System.out.println("Server Started...");
clientSocket = serverSocket.accept();
}catch(Exception e){};
Scanner in = new Scanner(clientSocket.getInputStream());
String inputLine;
while (true)
{
if(in.hasNext())
{
inputLine=in.nextLine();
System.out.println("Message from server: "+inputLine);
}
}
And here's the client code:
Socket client;
PrintWriter printwriter;
String serverIpAddress="192.168.173.1";
Button button;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button =(Button) findViewById(R.id.button);
text=(TextView) findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
client = new Socket(serverIpAddress,4444);
printwriter = new PrintWriter(client.getOutputStream());
printwriter.write("Start");
printwriter.flush();
//printwriter.close();
//client.close();
}
catch(UnknownHostException e)
{
}
catch(IOException e)
{
e.printStackTrace();
}
}
}).start();
}
});
}
I have one button, when I press it a message is sent to the server and it displays fine, but when I press the button the socket does not reconnect so I can't send the massage again.
To be clear I intend to eventually add more buttons to send different messages. I looked into creating a global socket but that didn't seem to go anywhere.
Any help is greatly appreciated.
This is because you are not closing the socket in the client code. You should close the streams & sockets in both server and client when the connection is over. Saying this, you should keep the connection alive and send several messages instead of closing the connection after sending one message.
I would for example rewrite the server code as (please note that this handles only one client):
ServerSocket serverSocket = null;
Socket clientSocket =null;
Scanner in = null;
try
{
serverSocket = new ServerSocket(4444);
System.out.println("Server Started...");
clientSocket = serverSocket.accept();
in = new Scanner(clientSocket.getInputStream());
String inputLine;
while (true) {
if(in.hasNext()) {
inputLine=in.nextLine();
System.out.println("Message from server: "+inputLine);
}
}
} catch(IOException e) {
e.printStackTrace();
} finally {
if(in != null) {
in.close();
}
if(clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Just a note: I would use DataInputStream & DataOutputStream... in this way, you could use in.readUTF() in the server side which will block until receiving something new through network. In this way, you will not have to do while(true) which will be way much better for the CPU.
Thank you all for your responses. I did get it working.
Multithreader, thank you, you were completely correct about where my problem lay. I did it a bit differently though.
I set up another class to set up the socket and created a method to start listening on the given port. In the main I just put that in a loop to keep closing and recreating the socket till the end condition is met.
Thanks again all.

Categories

Resources