I have a client which can send some information to a server via TCP :
public class IR {
private String host; //server IP address indicated here, I deleted it for posting here
private int port = 6789;
private String sentence;
private String reply;
public IR(String type) {
try {
Socket clientSocket = new Socket(host,port); //IP du server ("localhost" pour un server local) et port utilisé
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Gson gson = new GsonBuilder().create();
FileReader file = new FileReader("data/userInfo.json");
String json = "";
int i = 0;
while ((i = file.read()) != -1)
json += (char)i;
User user = gson.fromJson(json, User.class);
String user_id = user.getID();
int bus_id = user.getBusID();
sentence = "alerte " + type + " " + user_id + " " + bus_id;
System.out.println("SENTENCE: " + sentence);
outToServer.writeBytes(sentence + '\n');
reply = inFromServer.readLine();
System.out.println("ANSWER: " + reply);
clientSocket.close();
}
catch (Exception io) {
System.out.println("Connection refusée: arrêt");
}
}
}
I am calling this in my android application : I have a button which use this method when I'm clicking on it :
public void signalerComplet(View view)
{
client = new IR("complet");
Toast.makeText(this, "envoyé", Toast.LENGTH_SHORT).show();
}
But my server doesn't get anything .
Though, I ma sure that my client works when I'm using it not in my android application .
Could somebody say to me what I am missing here ?
EDIT after getting Hector's help : the server gets my "bloubloubloub" but I get an android.os.NetworkOnMainThreadException on the "int size = in.read(data);" ...
private Socket socket;
public void signalerComplet(View view)
{
PrintWriter out = null;
InputStream in=null;
byte[] data = new byte[5120];
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
}
catch (IOException e) {
e.printStackTrace();
}
out.println("bloubloubloub" + '\n');
out.flush();
try {
in = socket.getInputStream();
int size = in.read(data);
}
catch (IOException e) {
e.printStackTrace();
}
Log.e("data from server", data.toString());
}
type.equals(null) will always be false as if the variable type actually holds a null value it will throw a NullPointerException as there is no method equals for the null value. Therefore the if body will never execute.
The correct way to match if a variable is null is by the == operator.
if (type == null) {
// do this
} else {
// do that
}
equals() on a String should be used to compare against another String.
In Android you can't just put all this code in the onCreate method (for example) and run it, because you can't start a proccess that blocks the main thread, in this case Socket clientSocket = new Socket(host,port); will block the main thread and you app will crashes. You need do this tcp communication using threads. Please try this code and follow this algorithm:
Create this inner class, this will excecute the socket connection using threads:
class ClientThread implements Runnable {
#Override
public void run() {
try {
socket = new Socket(ipServer, portServer);
} catch (UnknownHostException e1) {
threadMsg("Connection fails");
} catch (IOException e1) {
threadMsg("Connection fails");
}
}
}
In onCreate Method call this
new Thread(new ClientThread()).start();
And in you send button should put something like this:
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
} catch (IOException e) {
e.printStackTrace();
}
out.println(messageToServer);
out.flush();
And this should send the string to server socket. Also you need add some basic validations.
EDIT: To get data from server, add this code in a new onClick button method:
byte[] data = new byte[5120];
try {
in = socket.getInputStream();
int size = in.read(data);
// see the received data from server in you LogCat
Log.e("data from server", data.toString());
} catch (Exception e) {
e.printStackTrace();
}
Hope it helps.
When you do:
client = new IR("complet");
You will fall at the else statement in your IR constructor which does nothing despite to close connection.
Here is what I've done . Thanks again to Hector for his help . It works great . Anything which could be "magnified" would be appreciated . :)
public class SignalerProblemeActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.signaler_probleme);
}
public void signalerComplet(View view)
{
new Thread(new CompletThread()).start();
Toast.makeText(this, "Signalement de bus complet envoyé", Toast.LENGTH_SHORT).show();
}
class CompletThread implements Runnable {
#Override
public void run() {
Socket socket=null;
User u = new User("momo",12);
String sentence="alerte complet "+u.getID()+u.getBusID();
try {
//CREATION SOCKET
socket=new Socket("123.456.789.10",6789);
//SENDING
PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
out.println(sentence);
//GETTING
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String mstr=br.readLine();
Log.e("CLIENT",mstr);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch(Exception e)
{
Log.e("CLIENT",e.toString());
}
}
}
}
Related
I have created a quizServer application in java swing that connects to multiple clients through a socket. I am able to send data to the server from each client simultaneously through the socket connection but when I try to send data to the clients from the server then it is being received by only 1 client. How can I modify the code to send data to all the clients listening on the socket at the same time? Any code/pseudo-code will be appreciated.
This is my NetworkClient class:
public class NetworkClient {
PrintWriter os = null;
Socket s1 = null;
String line = null;
BufferedReader br = null;
BufferedReader is = null;
InetAddress address = null;
void initClient() {
try {
address = InetAddress.getLocalHost();
System.out.println(address);
} catch (UnknownHostException ex) {
Logger.getLogger(NetworkClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
s1 = new Socket(address, 8888); // You can use static final constant PORT_NUM
br = new BufferedReader(new InputStreamReader(System.in));
is = new BufferedReader(new InputStreamReader(s1.getInputStream()));
os = new PrintWriter(s1.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
System.err.print("IO Exception");
}
}
void sendVal(int data) {
os.println(data);
os.flush();
}
void close() {
try {
is.close();
os.close();
br.close();
s1.close();
} catch (Exception ex) {
Logger.getLogger(NetworkClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Here is my Server class:
public class QuizServer {
QuizJFrame frame;
ServerThread st;
void initServer(QuizJFrame frm) {
frame = frm;
Socket s = null;
ServerSocket ss2 = null;
System.out.println("Server Listening......");
try {
ss2 = new ServerSocket(8888); // port number used as 8888
} catch (IOException e) {
e.printStackTrace();
System.out.println("Server error");
}
while (true) {
try {
s = ss2.accept();
System.out.println("connection Established");
st = new ServerThread(s, frm);
st.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Connection Error");
}
}
}
}
This is the server thread class:
class ServerThread extends Thread {
BufferedReader is = null;
PrintWriter os = null;
Socket s = null;
QuizJFrame frame;
String question[] = {"", "QUESTION 1", "QUESTION 2", "QUESTION 3", "QUESTION 4", "END"};
int answer[] = {0, 1, 2, 3, 4};
int index;
public ServerThread(Socket s, QuizJFrame frm) {
this.s = s;
frame = frm;
index = 1;
frame.setQuestion(question[index]);
}
#Override
public void run() {
int option = 0;
try {
is = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
System.out.println("IO error in server thread:" + e);
}
try {
while (option > -1) {
try {
option = Integer.parseInt(is.readLine());
os.println(answer[index] == option);
os.flush();
} catch (NumberFormatException e) { //to handle null value
}
System.out.println(result(option));
frame.output(result(option));
}
} catch (IOException ex) {
Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
String result(int op) {
if (op == -1) {
return "Client exited";
}
if (answer[index] == op) {
return "Option " + op + " is the correct answer.";
} else {
return "Option " + op + " is incorrect.";
}
}
void nextQues() {
index++;
frame.setQuestion(question[index]);
os.println(-2);
os.flush();
}
}
EDIT : Using List<ServerThread> resolved the issue.
Your server has only one ServerThread variable, and thus can only send data to one socket, the last one added. Instead, consider giving the class an List<ServerThread> variable to allow it to communicate with all the clients. Then in the while loop where you create connections, add each newly created ServerThread to this list.
You'll also need to fix your server's threading issues so that the while (true) loop doesn't block key code.
You'll also need to upgrade the ServerThread class so that the main server object can communicate with its streams.
Also you almost never want to have a class extend Thread. Have it implement Runnable instead.
I made a little game. Now i want to get the highscore from my Server. The code on the client:
private int getOnlineHighscore() {
int highscore = 0;
try {
socket = new Socket("localhost", 444);
input = socket.getInputStream();
System.out.println(input);
highscore = input.read();
input.close();
socket.close();
input = null;
socket = null;
} catch (Exception e) {
System.out.println("Verbindung fehlgeschlagen!");
}
System.out.println(highscore);
return highscore;
}
And on the Server:
import java.io.*;
import java.net.*;
public class ReadServer extends Thread {
private Socket socket;
public ReadServer(Socket socket) {
super();
this.socket = socket;
}
public void run() {
try {
System.out.println(socket.getInetAddress());
String result = "";
try (BufferedReader br = new BufferedReader(
new FileReader(System.getProperty("user.home") + "/AppData/Roaming/GameServer/.sg"))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
System.out.println("2");
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
System.out.println("3");
result = sb.toString();
System.out.println("3.5");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("4");
socket.getOutputStream().write(Integer.parseInt(result));
System.out.println(result);
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
public static void main(String[] Args) {
Socket socket = null;
ServerSocket server = null;
try {
server = new ServerSocket(444);
while (true) {
socket = server.accept();
new ReadServer(socket).start();
}
} catch (Exception e) {
}
try {
server.close();
} catch (Exception e) {
}
}
}
If I run it, the client function returns:
-1
The server writes in the console(not important I think):
/127.0.0.1
2
3
3.5
4
How to solve the problem? I want to send an int stored on my Server to a client.
-Jakob
-1 is returned by read() to specify end of stream , make sure data to be read is being returned .
What is the highscore stored in the file? I believe the file is empty and it fails on parsing the integer but as your catch block is empty, you don't see the exception. Put printStacktrace or rethrow.
Another problem is that OutputStream sends only bytes and therefore write method sends only low 8 bits. To send int wrap the stream with DataOutputStream and DataInputStream on the client side.
I'm new in network developing in Java and I want to create a simple Socket server, that get values from client and collects all of them in ArrayList. I wrote an example code, but in server side it not collecting the strings. This is my server side:
Server
public class ServerSideSocket extends Thread{
private ServerSocket serverSocket;
private Socket socket;
private ArrayList<String> list = new ArrayList<String>();
DataInputStream inData;
DataOutputStream outData;
public ServerSideSocket(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void run() {
while(true) {
try{
System.out.println("Waiting for connection...");
socket = serverSocket.accept();
System.out.println("Connected!" );
inData = new DataInputStream(socket.getInputStream());
outData = new DataOutputStream(socket.getOutputStream());
System.out.println(inData.readUTF());
list.add(inData.readUTF());
System.out.println("------------ VALUES ---------");
for (String value: list) {
System.out.println(value);
}
System.out.println("------------ END VALUES ---------");
outData.writeUTF("Message saved!");
outData.flush();
} catch (SocketException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inData.close();
outData.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
int port = 9999;
try {
Thread t = new ServerSideSocket(port);
t.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
and Client:
public class ClientSideSocket {
public static void main(String[] args) {
String serverName = "localhost";
int port = 9999;
String line = "";
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream out = client.getOutputStream();
DataOutputStream outData = new DataOutputStream(out);
InputStream in = client.getInputStream();
DataInputStream inData = new DataInputStream(in);
outData.writeUTF("Simple text");
outData.flush();
System.out.println("Response from server: " + inData.readUTF());
System.out.println("You can write more messages!");
System.out.println();
client.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
what is wrong in my code?
This happens because you try to read twice from the data stream by calling inData.readUTF() method. First call successfully reads data from the stream, but instead of saving result you try to perform another read 2 lines below.
readUTF() is blocking method and thus it waits for another portion of data which never comes from the same client. That's why your server hungs forever
What you want to do is to read once and store result into local variable:
String res = inData.readUTF();
list.add(res);
You are writing data once as "Simple Text" which you can read only once.
Where in your code you are first reading it
System.out.println(inData.readUTF());
list.add(inData.readUTF());
Instead of this you should first store it in a String and then use it.
String message = inData.readUTF();
System.out.println(message);
list.add(message);
I have created two android applications, a client and a server, utilizing TCP to communicate across devices. On the server, I have this code to listen for TCP communication:
private class StartServer implements Runnable {
public void run() {
getState(); // This just refreshes the server state
try {
serverSocket = new ServerSocket(5000);
appendLog("Server successfully listening ["+getLocalIpAddress() + ":5000]"); //appendLog function just uses runOnUiThread() to update the log textview
} catch (IOException e) {
appendLog("Could not listen on port: 5000");
//System.exit(-1);
}
BufferedReader in = null;
BufferedWriter out = null;
String input = null;
try {
clientSocket = serverSocket.accept();
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
while (serverState) { //variable set by our getState() function
input = in.readLine();
appendLog("Received: " + input);
this.gotMessage(out, input);
}
in.close();
out.close();
} catch (IOException e) {
//appendLog(e.toString());
appendLog("Accept failed: 5000");
//System.exit(-1);
}
}
Which calls this function to actually parse the recieved messages:
private void gotMessage(BufferedWriter output, String msg) {
if (msg != null) {
String sString = msg;
int to_do = 0;
if (msg.matches("^(?i)(exit|quit|close)$")) {
appendLog("Exiting");
sString = "Goodbye";
to_do=1;
} else if (msg.matches("^(?i)(launch|run|open)\\s(.+)")) {
appendLog("Launching application");
sString = "Launching application";
} else if (msg.matches("^(?i)(turn off|server off|deactivate)$")) {
appendLog("Turning off server due to remote command.");
sString = "Turning off...";
to_do=2;
} else if (msg.matches("^(?i)(restart|reboot)$")) {
appendLog("Resetting server");
sString = "Rebooting now...";
to_do=3;
}
try {
output.write("S: " + sString);
output.newLine();
output.flush();
} catch (IOException e) {
appendLog("Cannot parse message");
}
switch(to_do) {
case 0:
break;
case 1:
System.exit(0);
break;
case 2:
serverOff();
break;
case 3:
serverOff();
serverOn();
break;
default:
break;
}
}
}
}
The thread itself for the server is started using Thread t = new Thread(new StartServer()); t.start(). And to the best of my knowledge, this works fine. I can open up a terminal and telnet to the IP and port, and pass communication back and forth without error. But when I try to do the same from the client code below. I only get the first message, and anything else I pass in just dissappears into the void.
public void sendToServer(View v) {
try {
String ip = ((TextView)findViewById(R.id.ip_box)).getText().toString(); //User entered IP address
String to_send = ((EditText)findViewById(R.id.send_to_server)).getText().toString(); //User entered text to send
this.s = new Socket(ip, 5000);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
appendLog("Sending: " + to_send);
out.write(to_send);
out.newLine();
out.close();
} catch (Exception e) {
Log.d("error", e.toString());
}
}
Do you have line-end character in your to_send string? if no, just add out.newLine() to your client code:
appendLog("Sending: " + to_send);
out.write(to_send);
out.newLine();
You server code should look like this to support multiple clients:
// main server loop
while (serverIsActive) {
clientSocket = serverSocket.accept();
// spawn new thread for each client
ClientThread ct = new ClientThread(clientSocket);
ct.start();
}
ClientThread should work with client socket and have its own loop for reading lines. It should stop as soon as client closes socket:
class ClientThread {
...
public void run() {
....
while ((inputLine = in.readLine()) != null) {
// process client message
}
in.close();
}
}
I have two Java applications, where an Android client connects to a server on a computer and sends a message using BufferedWriter over websockets.
The client:
try {
toast("Sending...");
Socket sock = new Socket(ip, PORT);
OutputStream os = sock.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.flush();
bw.write("Hello Server!");
toast("Connected!");
} catch (UnknownHostException e) {
toast(e.getMessage());
} catch (IOException e) {
toast(e.getMessage());
}
The server:
public static void main(String[] args) {
ServerSocket server;
ConnectionThread ct;
Socket s;
ExecutorService es = Executors.newSingleThreadExecutor();
try {
System.out.println("Starting server...");
server = new ServerSocket(1337);
s = server.accept();
ct = new ConnectionThread(s);
es.execute(ct);
} catch (IOException ex) {
ex.printStackTrace();
}
}
The ConnectionThread class:
public class ConnectionThread implements Runnable {
private Socket sock;
private InputStream is;
private BufferedReader br;
private boolean online;
public ConnectionThread(Socket s) {
System.out.println("Creating connection thread.");
this.sock = s;
online = true;
}
#Override
public void run() {
String input = "";
try {
System.out.println("Starting to read...");
is = sock.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
while (online) {
input = br.readLine();
if(input != null){
System.out.print("Received message: ");
System.out.println(input);
}
}
br.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
When I run the server, and then the client, the client will show the "Connected!" toast, and the server's output will be:
Starting server...
Creating connection thread.
Starting to read...
So, it seems like the connection is actually being made, but the message does not arrive. Does anybody know why this could be happening?
Your server is expecting a complete line terminated by a newline. Try:
bw.write("Hello Server!");
bw.newLine();
Do it like this...
String s = new String();
while ((br.readLine())!=null) {
s = s+br.readLine();
System.out.print("Received message: ");
System.out.println(input);
}
}
And
bw.println("Hello Server");
I notice that you don't send an endline on your client, so the BufferedReader.readline() will never return, because it cannot match the \n-character. Try it again with
bw.write("Hello Server!\n");
on the client side.