Android Studio Connect to Socket server - java

I have a server running in Java using Eclipse (Here the full code):
public class Main {
public static void main(String[]args) {
// BBDD connection var
Connection con = null;
// Sockets
ServerSocket server = null;
try {
server = new ServerSocket(5010);
} catch (IOException e2) {System.out.println("Error at creating server, check if the port is in use");System.exit(-1);}
/*** MySQL driver loading***/
try {
Class.forName("com.mysql.jdbc.Driver");
System.out.println("MySQL driver is UP");
} catch (ClassNotFoundException e1) {System.out.println("Error loading MySQL driver");}
/*** Stablishing connection with the ddbb ***/
try {
con= (Connection) DriverManager.getConnection("jdbc:mysql://IP/Database", "username", "password");
System.out.println("Connection stablished");
} catch (SQLException e) {
System.out.println("SQL ERROR");
e.printStackTrace();
}
/*** Assigning thread for client ***/
System.out.println("Listening for new requests...");
while (true) {
try {
Socket clientSocket;
clientSocket = server.accept();
System.out.println("Connection stablished");
DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
DataOutputStream dos = new DataOutputStream(clientSocket.getOutputStream());
ThreadForClient client = new ThreadForClient(con, clientSocket, dis, dos);
Thread thread = new Thread(cliente);
thread .start();
} catch (IOException e) {System.out.println("Error making client socket");}
}
}
class ThreadForClient implements Runnable {
Connection con;
Socket clientSocket;
DataInputStream dis;
DataOutputStream dos;
public ThreadForClient(Connection con, Socket s, DataInputStream dis, DataOutputStream dos) {
this.con = con;
this.clientSocket = s;
this.dis = dis;
this.dos = dos;
}
#Override
public void run() {
try {
int opc = dis.readInt();
switch (opc) {
case 1:
String email = dis.readUTF();
Boolean result = existeUsuario(email);
dos.writeBoolean(result);
break;
default: break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Boolean userExists(String email) throws SQLException { // 1
email = email.toLowerCase();
Statement stmt;
stmt = con.createStatement();
ResultSet rs=stmt.executeQuery("select * from users where email = '"+email+"'");
boolean result = rs.first();
return result;
}
}
As you can see, the client sends 2 values and receives 1, the first one is for the switch, which will indicate what to exceute, for now I just have on option (checking if email exists in the ddbb), the second value is the email as the code has already entered the switch.
The server is fully working and I already tested it with a Client Test project in Eclipse (It is what I want to do in Android Studio):
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket(HOST, PORT);
System.out.println("Conection succesful");
DataOutputStream dos;
DataInputStream dis;
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
dos.writeInt(1);
dos.writeUTF("email#example.com");
Boolean bool = dis.readBoolean();
if (bool) {
System.out.println("Email exists in the BBDD.");
} else {
System.out.println("Email does not exist in the BBDD.");
}
socket.close();
} catch (Exception e) {System.out.println("Server connection failed");}
}
Now what I want to do is doing the same client in Android Studio so it can connect to the server.
I tried this:
public class SocketConnection {
UserExists ue;
public SocketConnection() throws IOException {
connect();
}
public void connect() {
ue = new UserExists();
ue.execute();
}
}
class UserExists extends AsyncTask<Void, Void, Void> {
int PORT = 5010;
String HOST = "192.168.1.5";
private Socket socket;
private DataOutputStream dos;
private DataInputStream dis;
#Override
protected Void doInBackground(Void... voids) {
try {
socket = new Socket(HOST, PORT);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
} catch (Exception e) {
System.out.println("Socket error");
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
When I run it it does not give me any error but if I log the socket value at doInBackground's bottom to see the socket value, it says it is null.
I also tried using Thread and Handle but I can't get the result the server gives me back to the main thread.

According to RFC 1918, addresses in the 192.168.0.0-192.168.255.255 range are private. Such addresses can be used internally by any network so they're often used inside an organization. They cannot be used on the Internet since they aren't unique. Why my ip address starts with 192.?
I think that your local network is somehow preventing that connection. But without further details nobody can actually tell as far I know.
If you are running everything on the same computer you may want to take a look at "loopback" address. Usually 127.0.0.1 , that should loop back to your machine.
If you want to run a full server you may need to dig more into networking and want to understand how networks function.

I managed to resolve this. I just made a thread inside a "Connection" class in Android Studio.
Inside "Connection" I have some class-level variables, which I use with the thread (The thread can't modify variables in the method the thread was created but it can read class-level variables) so the thread itself makes the connection with the socket server and saves the value taken to also a class-level variable.
In the main thread (in the same method that called the thread) I used a loop that looks at the thread status, if it has finished, reads the variable and applies it where I want.
Here the code:
public class Connection{
private String HOST = "83.xx.xx.xx";
private int PORT = 5010;
private Socket socket;
private DataOutputStream dos;
private DataInputStream dis;
boolean result;
String email;
public boolean userExists(String dev) throws InterruptedException { // true = exists, false = does not exist. dev is the email to search
this.email = dev;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
socket = new Socket(HOST, PORT);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream((socket.getInputStream()));
dos.writeInt(1); // 1 = Sends the option for telling the server that we want to search a user
dos.writeUTF(email); //Sends the email
result = dis.readBoolean(); // Recieve if email exists or not
socket.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Couldn't connect to server");
}
}
});
thread.start();
for (int c=0; c<25; c++){ //Wait for the thread to end
if (thread.isAlive()) {
//Thread hasn't finished yet...
Thread.sleep(100);
} else if (c == 24) {
//This would be a timeout
result = false;
} else {
//Thread has finished
break;
}
}
return result; // true in case server found the email, false in case it doesn't or in case of a timeout
}
I think another possibility could be making the thread just do the connection (and another one for closing it) and saving the socket as class-level variable, so you can send and receive from the main thread, I didn't try it tho.

Related

How can I break a while loop with ServerSocket.accept() inside without throwing exception?

I connect multiple clients to a server using Sockets and a ServerSocket. Currently my servers run() method has a while(bool) loop that creates a new socket whenever a client tries to connect but I want to break the loop from another method. Sounds easy but simply changing the boolean to false won't do since something waits on serverSocket.accept() for it to, well, accept.
Using setSoTimeout didn't work for me, as it throws an exception. I need the thread to loop and wait for new clients until one of them sends a "CLOSE" String via Stream, not for a set period of time, but I could be doing something wrong. I would like to keep serverSocket in try-with-resources so that everything closes when I close the JFrame with mouseclick, still I need it to close from code too. I also tried creating a "Ghost" client that should break the cycle but I think it's not an elegant solution and now I get socket closed exception in ClientThread first line ine while loop. I am so lost please help me.
the code:
class ClientThread implements Runnable{
private Socket socket;
private String name;
private boolean running;
private PhoneBookServer server;
private ObjectOutputStream outputStream = null;
ClientThread(PhoneBookServer server, Socket socket){
this.server = server;
this.socket = socket;
new Thread(this).start();
}
public String getName(){
return name;
}
public void disconnect(){
try {
outputStream.writeObject("OK BYE");
server.printMessage("OK BYE");
running = false;
socket.close();
socket = null;
}catch (IOException e){
e.printStackTrace();
}
}
public void run(){
String message;
try(ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());){
outputStream = output;
name = (String) input.readObject();
running = true;
server.addClient(this);
while(running){
message = (String) input.readObject();
server.printMessage(this, message);
if(message.equals("BYE")){
disconnect();
server.removeClient(this);
}
if(message.equals("CLOSE")){
server.disconnectAll();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
interesting methods from the Server class:
synchronized void disconnectAll(){
for(ClientThread c : connectedClients){
c.disconnect();
}
running = false;
}
public void run(){
boolean socket_created = false;
try(ServerSocket serverSocket = new ServerSocket(SERVER_PORT)){
String host = InetAddress.getLocalHost().getHostName();
System.out.println("Serwer został uruchomiony na hoście " + host);
socket_created = true;
while(running){
Socket socket = serverSocket.accept();
if (socket != null){
new ClientThread(this, socket);
}
}
}catch (IOException e){
e.printStackTrace();
}
}
}

Java Server producing inconsistent output

I want to integrate a server with multiple clients for a blackjack game I created, and thus I began practicing with servers in java. I create a thread, that when ran, forces the server to listen for input and produce an output. Then I added a feature to stop the server. However, the server randomly produces the correct output, and sometimes fails to connect. Here is the code for when the user hosts a server:
st = new ServerThread(); //this is a field of type ServerThread
st.start(); //this runs the server concurrently as a new thread
Here is the code for when they close a server:
st.stopThread();
Finally, here is the source for the serverThread:
public class ServerThread extends Thread {
private volatile boolean isRunning = true;
private Socket socket;
private static final int PORTNUM = 1342;
#Override
public void run() {
while (isRunning) { //should run only when the
try {
ServerSocket serverSocket = new ServerSocket(PORTNUM); //uses the same port number, which I made a constant
//Reading the an object of type Information from the client
socket = serverSocket.accept();
ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
Information i = (Information) serverInputStream.readObject();
//arbitrarily changes the data stored in the information object to verify connection with server
i.setI(100);
i.setS("new string");
i.setD(4.4);
//sends the modified object back to the client
serverOutputStream.writeObject(i);
serverInputStream.close();
serverOutputStream.close();
socket.close();
} catch (IOException e) {
//System.out.println("IOException");
//e.printStackTrace();
} catch (ClassNotFoundException e) {
//System.out.println("ClassNotFoundException");
//e.printStackTrace();
} finally {
try {
if (socket != null) { //avoid null pointer if no connections have been established
socket.close();
}
} catch (IOException ex) {
//Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void stopThread() {
isRunning = false;
}
}
Any suggestions on edits to make my code perform correctly and consistently would be welcome. Thanks.
I would move the socket definition away from being an instance variable i.e,
while (isRunning) {
Socket socket = null;
try {
...

Maximum socket connections available

I am trying my hand at socket programming. I built a simple echo server that prints the client text on the screen and sends back a thank you message to the client. However when I run the client (which individually spawns 10000 requests in a loop) sometimes i get "connection refused" exceptions in some client threads. Sometimes all go through without any exception.
Following is my server code :
public class WebServer {
static int hitCount = 0;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(7777, 10000);
while (true) {
Socket defaultSocket = serverSocket.accept();
new Thread(new ServerSlave(defaultSocket)).start();
System.out.println("Size is :" + hitCount);
}
}
}
class ServerSlave implements Runnable {
Socket clientSocket;
public ServerSlave(Socket socket) {
clientSocket = socket;
WebServer.hitCount++;
}
public void run() {
try {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println(inputStream.readUTF());
outputStream.writeUTF("Thank you for contacting the web server");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Following is my client code :
public class Client {
static int excepCount=0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
new Thread(new Worker("" + i)).start();
}
Thread.sleep(10000);
System.out.println( Client.excepCount);
}
}
class Worker implements Runnable {
String clientName;
public Worker(String name) {
clientName = name;
}
public void run() {
System.out.println("Process started for : " + clientName);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello socket. Client number " + clientName + "here");
InputStream inFromServer = socket.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
System.out.println("Closing socket");
} catch (IOException e) {
Client.excepCount++;
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Not sure what I might be doing wrong. Any suggestions ?
You're expecting too much. It just isn't realistic for a client to form 10,000 connections at maximum speed. You're forgetting about the TIME_WAIT state, and the fact that there are only 64k minus several dozen client-side ports available. It isn't a realistic test. If you want to load-test your server you will need quite a few client hosts, or a longer interval between connections.

Java Sockets - EOFException when trying to implement multi-threading

I think it's because when I multi-thread the client&server, the DataOutputStream and DataInputStream buffers I use get overwritten or something like that since the socket can only have 1 duplex connection.
Here's what I have for now:
Client Class in my client program:
public static void main(String args[]) throws UnknownHostException, IOException, InterruptedException {
for (int i=0;i<2;i++) //change limit on i to change number of threads
{
new Thread(new ClientHandler(i)).start();
}
Thread.sleep(10000);
ClientHandler class in my client program:
(Sends a value to the server, the server will echo it back).
public class ClientHandler implements Runnable {
public int clientNumber;
public ClientHandler(int i){
this.clientNumber=i;
}
public void run() {
Socket socket = null;
try {
socket = new Socket("localhost",9990);
System.out.println("connected client number "+clientNumber);
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
output.writeDouble((new Random()).nextDouble());
System.out.println(input.readDouble());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Server Class in my server program:
ServerSocket socket = new ServerSocket(9990);
try {
while (true) {
Socket threadSocket = socket.accept();
new Thread(new ServerHandler(threadSocket)).start();
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
socket.close();
}
}
}
ServerHandler Class in my server program (receives value from client and echoes it back)
public class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
public void run() {
while(true) {
try {
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
double a = input.readDouble();
output.writeDouble(a);
}catch (IOException e){
e.printStackTrace();
}
}
}
So it's a pretty straight-forward implementation: create multiple threads of the client, and connect them to multiple threads of the server.
Everything works fine until the line:
double a = input.readDouble();
in my ServerHandler class.
I get an EOFException
I'm guessing it's because there can only be a single duplex connection between sockets. But if that's the case then how would I implement multi-threading of sockets at all?
So my question is: how can I get rid of the EOFException and allow myself to perform multi-threaded client-server socket interaction?
(preferably not changing much about my code because it's taken me a long time to get to this point).
The problem is that you share same Socket variable in ServerHandler for all threads:
private static Socket socket
Remove static keyword. Your ServerHandler will be something like this:
public static class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
double a = input.readDouble();
output.writeDouble(a);
} catch (IOException e) {
e.printStackTrace();
}
}
}

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