I'm developing an asynchronous socket client based on threads. When the program calls readLine(), it blocks indefinitely and never returns.
public class ADNClient {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
Thread listener = new Thread(new Runnable() {
#Override
public void run() {
String line;
try {
// Stop here and doesn't progress
while ((line = dataInputStream.readLine()) != null) {
//DO something
}
}
catch (IOException e) {}
});
public ADNClient() {
try {
socket = new Socket("192.168.1.5", 5000);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
listener.start();
//sender.start();
} catch (Exception e) {
Log.e("ADN", e.getMessage());
}
}
public void close() {
listener.stop();
try {
socket.close();
} catch (IOException e) {
Log.e("ADN", e.getMessage());
}
}
}
Ok... I'm noob with IN/Outputstreams... I didn't send the newline character, the correct way to recive information is using
readUTF()
instead of
readLine()
Thank you Greg Kopff!
Related
The program is intended to have multiple clients connect to a single server and the clients are able to send and receive messages among other clients.
For example if Client A says "Hi", Client B and Client C connected to the server would also receive "Hi".
In my current code, the server only receives the messages sent by the clients.
I'm currently looking for a solution to have the server broadcast the message sent by a client (eg. ClientA) to other clients. Any advice would be much appreciated.
This server class handles the connections of multiple clients with the use of threads:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
class EchoThread extends Thread {
private Socket socket;
//constructor
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
}
#Override
public void run() {
DataInputStream inp = null;
try {
inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//print whatever client is saying as long as it is not "Over"
String line = "";
while (!line.equals("Over")) {
try {
line = inp.readUTF();
System.out.println(line);
} catch (IOException e) { System.out.println(e); }
}
//closes connection when client terminates the connection
System.out.print("Closing Connection");
socket.close();
} catch (IOException e) { System.out.println(e); }
}
}
public class Server {
private static final int PORT = 5000;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
//starts the server
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Server started");
System.out.println("Waiting for a client ...\n");
} catch (IOException e) { System.out.println(e); }
//while loop to accept multiple clients
int count = 1;
while(true) {
try {
socket = serverSocket.accept();
System.out.println("Client " + count + " accepted!");
count++;
} catch (IOException e) { System.out.println(e); }
//starts the server thread
new EchoThread(socket).start();
}
}
}
and this is the client class (I have multiple instances of this code running):
import java.net.*;
import java.io.*;
public class ClientA {
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream output = null;
public ClientA(String address, int port) {
//establish connection
try {
socket = new Socket(address, port);
System.out.println("Connected");
//takes input from terminal
input = new DataInputStream(System.in);
//sends output to the socket
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) { System.out.println(e); }
//string to read message from input
String line = "";
//keep reading until "Over" is input
while (!line.equals("Over")) {
try {
line = input.readLine();
output.writeUTF(line);
} catch (IOException e) { System.out.println(e); }
}
//close the connection
try {
input.close();
output.close();
socket.close();
} catch (IOException e) { System.out.println(e); }
}
public static void main (String args[]) {
ClientA client = new ClientA("127.0.0.1", 5000);
}
}
Do feel free to correct me on my code comments as I'm still not very familiar with socket programming.
You did well. Just add a thread to receive message in ClientA; and store socket clients in Server.
In fact, Server is also a "client" when is send message to client.
I add some code based on your code. It works well, hope it's helpful.
class EchoThread extends Thread {
//*****What I add begin.
private static List<Socket> socketList = new ArrayList<>();
//*****What I add end.
private Socket socket;
//constructor
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
socketList.add(socket);
}
#Override
public void run() {
DataInputStream inp = null;
try {
inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//print whatever client is saying as long as it is not "Over"
String line = "";
while (!line.equals("Over")) {
try {
line = inp.readUTF();
System.out.println(line);
//*****What I add begin.
sendMessageToClients(line);
//*****What I add end.
} catch (IOException e) { System.out.println(e); break;}
}
//closes connection when client terminates the connection
System.out.print("Closing Connection");
socket.close();
} catch (IOException e) { System.out.println(e); }
}
//*****What I add begin.
private void sendMessageToClients(String line) throws IOException {
for (Socket other : socketList) {
if (other == socket) {
continue;//ignore the sender client.
}
DataOutputStream output = new DataOutputStream(other.getOutputStream());
output.writeUTF(line);
}
}
//*****What I add end.
}
public class ClientA {
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream output = null;
public ClientA(String address, int port) {
//establish connection
try {
socket = new Socket(address, port);
System.out.println("Connected");
//takes input from terminal
input = new DataInputStream(System.in);
//sends output to the socket
output = new DataOutputStream(socket.getOutputStream());
//*****What I add begin.
//Here create a thread to receive message from server.
DataInputStream inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
new Thread(() -> {
while (true) {
String str;
try {
str = inp.readUTF();
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();//error.
break;
}
}
}, "Client Reveiver.").start();
//*****What I add end.
} catch (IOException e) { System.out.println(e); }
//string to read message from input
String line = "";
//keep reading until "Over" is input
while (!line.equals("Over")) {
try {
line = input.readLine();
output.writeUTF(line);
} catch (IOException e) { System.out.println(e); }
}
//close the connection
try {
input.close();
output.close();
socket.close();
} catch (IOException e) { System.out.println(e); }
}
I would have a single server thread which would maintain a register of the clients, possibly in a concurrent collection. Then I would send each message received from a client to all other clients.
I am trying to create a peer-to-peer voice-chat program that is attempting to establish connection between two peers at the beginning of the program.
I have created two threads, one thread Call that handles users request to call someone and receiveCall that handles incomming calls.
What I want to do is that when you either get a call or call someone is to "kill" the other thread because it served it's purpose.
The method that creates the two threads.
public Peer(String[] args) {
port = Integer.parseInt(args[0]);
stateHandler = new StateHandler();
scanner = new Scanner(System.in);
call = new Thread(new ReceiveCall());
call.start();
receiveCall = new Thread(new Call());
receiveCall.start();
}
The Call method:
class Call implements Runnable {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.print(">");
String ip;
int port;
DataOutputStream output;
String call;
call = scanner.nextLine();
while (!call.contains("call") && findMatches(call, " ") != 2 && !callFlag) {
System.out.println("Usage: call <ip> <port>");
call = scanner.nextLine();
}
String[] parts = call.split(" ");
ip = parts[1];
port = Integer.parseInt(parts[2]);
socket = new Socket(ip, port);
//Send invite
output = new DataOutputStream(socket.getOutputStream());
output.writeUTF("INVITE");
stateHandler.manageStates(StateHandler.StateEvent.CALLING, socket);
} catch (IOException e) {
Thread.currentThread().interrupt();
}
}
}
}
The ReceiveCall method:
class ReceiveCall implements Runnable {
#Override
public void run() {
DataInputStream inputStream;
DataOutputStream outputStream = null;
String answer, msg = null;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
//Accept connection
try {
socket = serverSocket.accept();
call.interrupt(); //Here I want to interrupt the other thread
inputStream = new DataInputStream(socket.getInputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
msg = inputStream.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
if (!msg.equals("INVITE")) {
}
System.out.println(socket.getInetAddress().toString() + " is calling you! Answer? (Y/N)");
synchronized (scanner) {
answer = scanner.nextLine();
}
if (!answer.equals("Y")) {
System.out.println("Ready to receive a call or call...");
}
try {
outputStream.writeUTF("TRO");
} catch (IOException e) {
e.printStackTrace();
}
stateHandler.manageStates(StateHandler.StateEvent.RECEIVE_CALL, socket);
}
}
The program is statebased so when one of the threads complete it is supposed to go to another state and execute the appropriate code there.
I'm trying to create a proxy application, but I'm facing problems in server socket. The Server Socket is not accepting the connection and returning a socket. Hence, I cannot test the proxy application. What is wrong?
The problem line is indicated in WebServe.java:
public class WebServe implements Runnable {
Socket soc;
OutputStream os;
BufferedReader is;
String resource;
WebServe(Socket s) throws IOException {
soc = s;
os = soc.getOutputStream();
is = new BufferedReader(new InputStreamReader(soc.getInputStream()));
}
public void run() {
System.err.println("Running");
getRequest();
returnResponse();
close();
}
public static void main(String args[]) {
try {
System.out.println("Proxy Thread");
ServerSocket s = new ServerSocket(8080);
for (;;) {
s.setSoTimeout(10000);
WebServe w = new WebServe(s.accept()); // Problem is here
Thread thr = new Thread(w);
thr.start();
w.getRequest();
w.returnResponse();
w.close();
}
} catch (IOException i) {
System.err.println("IOException in Server");
}
}
void getRequest() {
System.out.println("Getting Request");
try {
String message;
while ((message = is.readLine()) != null) {
if (message.equals("")) {
break;
}
System.err.println(message);
StringTokenizer t = new StringTokenizer(message);
String token = t.nextToken();
if (token.equals("GET")) {
resource = t.nextToken();
}
}
} catch (IOException e) {
System.err.println("Error receiving Web request");
}
}
void returnResponse() {
int c;
try {
FileInputStream f = new FileInputStream("." + resource);
while ((c = f.read()) != -1) {
os.write(c);
}
f.close();
} catch (IOException e) {
System.err.println("IOException is reading in web");
}
}
public void close() {
try {
is.close();
os.close();
soc.close();
} catch (IOException e) {
System.err.println("IOException in closing connection");
}
}
}
public static void main(String args[]){
try {
System.out.println("Proxy Thread");
ServerSocket s = new ServerSocket (8080);
for (;;){
s.setSoTimeout(10000);
Move that ahead of the loop. You don't need to keep setting it. You don't really need it at all actually.
WebServe w = new WebServe (s.accept()); //Problem is here
The problem is here only because you set a socket timeout you don't actually need.
Thread thr = new Thread (w);
thr.start();
So far so good.
w.getRequest();
w.returnResponse();
w.close();
Remove. The next problem is here. The run() method of WebServ already does this.
As to the rest, you aren't writing an HTTP header in the response.
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.
Problem:
I have written one java socket server which send response when I send first message from the client to it. But I want to send one more message based on the first response. After the first response i am not getting any other response?
Here is the Server code:
public class SendSmsServerSocket {
private final static CxpsLogger logger = CxpsLogger.getLogger(SendSmsServerSocket.class);
SendSmsServerSocket(){
try {
new SeverSocketForSms(new ServerSocket(4330));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class SeverSocketForSms extends Thread {
private Socket socket;
private ServerSocket serversocket;
private volatile static boolean running = true;
public SeverSocketForSms(ServerSocket ssocket) throws IOException {
this.serversocket = ssocket;
start();
}
public void run() {
try{
while(running) {
this.socket = serversocket.accept();
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : "+msg);
}
}
catch(Exception e){
e.printStackTrace();
}
catch(Throwable t) {
System.out.println("Caught " + t + "xmlServerThread - closing thread");
}
}
public static void shutdown() {
System.out.println("Stopping socket connection and thread");
try{
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
running = false;
}
public static void main (String [] args){
try {
System.out.println("Starting sms server ----- Please press Enter Key to stop the server after receiving one message");
SendSmsServerSocket s=new SendSmsServerSocket();
new Scanner(System.in).nextLine();
SeverSocketForSms.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Once you have an incoming connection, you should delgate the responsibility for handling that incoming connection to another Thread, otherwise you will block your "accept" thread until the current connection is closed...
while (running) {
this.socket = serversocket.accept();
Thread thread = new Thread(new Handler(socket));
thread.start();
}
And the Handler
public class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket){
this.socket = socket;
}
public void run() {
// You may need to add a repeat and exit clause here...
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : " + msg);
}
}