Reputation: 19
I'm trying to create a client/server application where, a laptop acts like server and share its internet connection with an android phone that acts like client, I can enstablish the connection between client and server, the problem is that when the client try to write on the socket, it get stuck there. This is the android xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.giuseppe.client">
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
This is the android client
package com.example.giuseppe.client;
import java.io.*;
import java.net.*;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import org.w3c.dom.Text;
import static java.net.InetAddress.*;
public class MainActivity extends Activity {
private Socket socket;
private static final int port=5555;
private static final String addr="192.168.1.37";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Client()).start();
}
public void onClick(View view){
try{
TextView tx=(TextView) findViewById(R.id.txt);
EditText et= (EditText) findViewById(R.id.et);
String str= et.getText().toString();
DataOutputStream out= new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())) ;
out.writeUTF(str);
out.close();
socket.close();
}catch(UnknownHostException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
class Client implements Runnable {
@Override
public void run() {
try {
TextView tx= (TextView) findViewById(R.id.txt);
tx.setText("Before connection");
InetAddress server = InetAddress.getByName(addr);
socket = new Socket("192.168.1.37", port);
tx.setText("After connection");
} catch (UnknownHostException a) {
} catch (IOException a) {
} catch (Exception a){
}
}
}
This is the server code
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
int port=5555;
byte[] buff =new byte[1024];
String str;
// TODO Auto-generated method stub
try {
ServerSocket server=new ServerSocket(port);
System.out.println("Before accept");
Socket client=server.accept();
System.out.println("After accept");
DataInputStream in=new DataInputStream(new BufferedInputStream(client.getInputStream()));
str=in.readUTF();
System.out.println("Message received");
in.close();
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I suppose the problem is in the client because I also tried to use the server to send a string and while the server send it, the client doesn't receive it. Sorry for my bad english. Thanks to all
+++++EDIT+++++
I tried also OutputStream out=socket.getOutputStream(); and then out.write(str.getBytes()), but in this case it get stuck here, when I try to write in the socket, could be any android's configuration the problem?
Upvotes: 0
Views: 142
Reputation: 16
That is an Art Producer / Consumer Problem. After the Server return from accept , the Client has an etablished Connection to the Server. While the Sever is waiting for data to read (Consumer) , The Client (Producer ) is doing nothing. The Client should write something on The Socket In order to continue.
Upvotes: 0
Reputation: 14668
Disclaimer: I cannot validate the correctness of your Android code so I am assuming that is fine, and only commenting on your networking code, which is the root cause of your issue.
2 main problems in your code are:
You main problem is #1 above and as soon as you resolve your #1, you will get another problem which is #2.
Your #1 problem is that you need to define some logic on how you want to consider the end of stream or input, refer below code example (read the comments in the code), also you don't necessarily need to use readUTF
method, instead you can use "I/O bridge classes" like InputStreamReader
which acts as a bridge between your byte stream and character stream, so you can use InputStreamReader clientSocketReader = (new InputStreamReader(clientSocket.getInputStream(), "UTF8"));
, and I cannot say why you really need DataInputStream
and can't use a InputStreamReader
but in my opinion you can go for using a bridge class.
int portNumber = 8001;
try {
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) { // **** this basically means that read one full line, you have to specify condition like this, so suppose you have created a telnet session with this server now keep on typing and as soon you will hit entered then while block processing will start.
System.out.println("@@@ " + inputLine);
out.println(inputLine); // *** here same input is written back to the client, so suppose you have telnet session then same input can be seen
}
} catch (IOException e) {
System.out.println(
"Exception caught when trying to listen on port " + portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
Now your #2 problem is that your server is single threaded, you need to have a multi-threaded server which basically means that you should process each client request in a new thread. Read this answer of mine which throws more light on single threaded v/s multi-threaded server. See below code example for a multi-threaded server:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import com.learn.Person;
/**
* @author himanshu.agrawal
*
*/
public class TestWebServer2 {
public static void main(String[] args) throws IOException {
startWebServer();
}
/**
* test "backlog" in ServerSocket constructor
test -- If <i>bindAddr</i> is null, it will default accepting
* connections on any/all local addresses.
* @throws IOException
*/
private static void startWebServer() throws IOException {
InetAddress address = InetAddress.getByName("localhost");
ServerSocket serverSocket = new ServerSocket(8001, 1, address);
// if set it to 1000 (1 sec.) then after 1 second porgram will exit with SocketTimeoutException because server socket will only listen for 1 second.
// 0 means infinite
serverSocket.setSoTimeout(/*1*/0000);
while(true){
/*Socket clientSocket = serverSocket.accept();*/ // a "blocking" call which waits until a connection is requested
System.out.println("1");
TestWebServer2.SocketThread socketThread = new TestWebServer2().new SocketThread();
try {
socketThread.setClientSocket(serverSocket.accept());
Thread thread = new Thread(socketThread);
thread.start();
System.out.println("2");
} catch (SocketTimeoutException socketTimeoutException) {
System.err.println(socketTimeoutException);
}
}
}
public class SocketThread implements Runnable{
Socket clientSocket;
public void setClientSocket(Socket clientSocket) throws SocketException {
this.clientSocket = clientSocket;
//this.clientSocket.setSoTimeout(2000); // this will set timeout for reading from client socket.
}
public void run(){
System.out.println("####### New client session started." + clientSocket.hashCode() + " | clientSocket.getLocalPort(): " + clientSocket.getLocalPort()
+ " | clientSocket.getPort(): " + clientSocket.getPort());
try {
listenToSocket(); // create this method and you implement what you want to do with the connection.
} catch (IOException e) {
System.err.println("#### EXCEPTION.");
e.printStackTrace();
}
}
}
}
Upvotes: 1