Java Socket Programming frame not responsive and loopy request - java

I'm trying socket programming for the first time and try codes from https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/SocketProgramming/SocketProgram.html and implement it to a frame. Clients can connect to the server, but there are some problem with my server frame like it's not responsive. And the request handler is ok for the first use per client, and not working for the next request. I notice that the handler looks like having a loop which I don't know why it's happening.
How the server react when the request made
This is how I start the server
private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {
try {
server = new ServerSocket(8005);
executor = Executors.newFixedThreadPool(5);
System.out.println("Waiting for clients");
while (true) {
socket = server.accept();
Runnable worker = new RequestHandler(socket);
executor.execute(worker);
System.out.println("check executor");
}
} catch (Exception e) {
System.out.println(e);
} finally{
if(executor!=null){
executor.shutdown();
}
}
}
The request handler
public class RequestHandler implements Runnable {
private Socket socket;
ServerSocket server = null;
public RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String userInput = in .readLine();
while (userInput != null) {
System.out.println("Received Message from " + Thread.currentThread().getName() + ": " + userInput);
jtaLog.append("Received Message from " + Thread.currentThread().getName() + ": " + userInput);
writer.write("You write : " + userInput);
writer.newLine();
writer.flush();
}
} catch (Exception e) {
System.out.println(e);
}
}
}
And from the client program the request made like this
private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {
try {
String message = tfMessage.getText();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println(message);
jtaLog.append( in .readLine() + "\n");
} catch (Exception e) {
System.out.println(e);
}
}

Related

Python Socket Only get information when the socket is closed

I am creating a program to play chess through the socket. My client is written in Python which is using socket to send data to the server. I receive information only when client program gets closed. Below mentioned is the client code. I am using python socket https://docs.python.org/3/library/socket.html
def youSecond(board):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.11.46', 9999))
run = True
turn = 1
new_msg = True
while run:
renderMap(board)
move = s.recv(1024).decode("utf-8")
if new_msg:
new_msg = False
print("SERVER: ", move)
players[0].play(board, move)
new_msg = True
turn +=1
renderMap(board)
print("Black machine is thinking.....")
myTurn = players[1].play(board, turn).encode("utf-8")
s.send(myTurn)
turn += 1
and my server using Java
public class ClientHandler implements Runnable {
BufferedReader reader;
Socket sock;
PrintWriter client;
public ClientHandler(Socket clientSocket, PrintWriter user) {
client = user;
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
System.out.println("tren helllo");
} catch (Exception ex) {
ta_chat.append("Unexpected error... \n");
}
}
#Override
public void run() {
String message, connect = "Connect", disconnect = "Disconnect", chat = "Chat";
String[] data;
try {
while ((message = reader.readLine()) != null) {
System.out.println("duoi helllo");
ta_chat.append("Received: " + message + "\n");
data = message.split(":");
for (String token : data) {
ta_chat.append(token + "\n");
}
if (data[2].equals(connect)) {
tellEveryone((data[0] + ":" + data[1] + ":" + chat));
userAdd(data[0]);
} else if (data[2].equals(disconnect)) {
tellEveryone((data[0] + ":has disconnected." + ":" + chat));
userRemove(data[0]);
} else if (data[2].equals(chat)) {
tellEveryone(message);
try {
FileWriter fw = new FileWriter("C:\\Users\\Admin\\Desktop\\FixCoTuong\\moves.txt");
fw.write(data[1]);
fw.close();
} catch (Exception e) {
System.out.println(e);
}
System.out.println("sucess");
} else {
ta_chat.append("No Conditions were met. \n");
}
}
} catch (Exception ex) {
ta_chat.append("Lost a connection. \n");
ex.printStackTrace();
clientOutputStreams.remove(client);
}

why it says that there is no line in the clients InputStream?(socket programming)

I tried to write a simple program that runs a server and then accepts two clients. Then one of them tries to send a string to another client.
but my code doesn't work and I don't know why.
This is my TestClient class:
public class TestClient extends Thread{
int id;
String Name;
Socket client;
boolean isAsk;
public TestClient(int id,String clientName,boolean isAsk) throws IOException {
this.id=id;
this.Name=clientName;
this.isAsk=isAsk;
}
public void connectTheClientToTheLocalHost(ServerSocket server){
try {
client = new Socket("localhost",1111);
server.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFromTerminal(){
try {
InputStream is=client.getInputStream();
OutputStream os = client.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println("sdklfsdklfk");
pw.flush();
pw.close();
}catch (IOException e){
e.printStackTrace();
}
}
public void closeTheCientSocket(){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void write(){
try {
Scanner sc = new Scanner(client.getInputStream());
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("file1.txt")));
String st =sc.nextLine();
bw.write(st);
bw.close();
}catch (IOException e){
e.printStackTrace();
}
}
#Override
public void run() {
if(isAsk){
readFromTerminal();
}
else{
write();
}
}
and this is the main function:
public class PCServer {
public static void main(String[] args){
try {
ServerSocket s = new ServerSocket(1111);
TestClient t1=(new TestClient(1,"reza",true));
TestClient t2=(new TestClient(2,"man",false));
t1.connectTheClientToTheLocalHost(s);
t1.start();
Scanner sc = new Scanner(t1.client.getInputStream());
String st=sc.nextLine();
System.out.println(st);
t1.closeTheCientSocket();
t2.connectTheClientToTheLocalHost(s);
PrintWriter pw = new PrintWriter(t2.client.getOutputStream());
pw.println(st);
pw.flush();
t2.start();
t2.closeTheCientSocket();
}catch (Exception e){
e.printStackTrace();
}
}
}
actually this code returns an exception in
String st=sc.nextLine();
in main function and says that there is no line found.
what is the problem?
ServerSocket in java usually used in another way.
If you need point-to-point connection, one host creates a ServerSocket and accepts connections. Examples:
First host example:
try(ServerSocket serverSocket = new ServerSocket(5555);
Socket socket = serverSocket.accept();
// it more convenient to use DataInputStream instead of Scanner I think
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());) {
while (!Thread.currentThread().isInterrupted()) {
String msg = dataInputStream.readUTF();
System.out.println("got request: " + msg);
dataOutputStream.writeUTF("1-response");
dataOutputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
Second host example:
try(Socket socket = new Socket("127.0.0.1", 5555);
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
while (!Thread.currentThread().isInterrupted()) {
dataOutputStream.writeUTF("2-request");
dataOutputStream.flush();
String msg = dataInputStream.readUTF();
System.out.println("got response: " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
If you want one host talk to another over the server (broker), then you need plane java Sockets on hosts and ServerSocket on broker, and broker must transmit messages it received from one host to another. Examples:
Broker (run it in separate thread or process)
try {
List<Socket> sockets = new ArrayList<>();
ServerSocket serverSocket = new ServerSocket(5555);
// accepting connections from 2 clients
for (int i = 0; i < 2; i++) {
Socket socket = serverSocket.accept();
sockets.add(socket);
}
// streams for first host
InputStream hostOneInputStream = sockets.get(0).getInputStream();
DataInputStream hostOneDataInputStream = new DataInputStream(sockets.get(0).getInputStream());
DataOutputStream hostOneDataOutputStream = new DataOutputStream(sockets.get(0).getOutputStream());
// streams for second host
InputStream hostTwoInputStream = sockets.get(1).getInputStream();
DataInputStream hostTwoDataInputStream = new DataInputStream(sockets.get(1).getInputStream());
DataOutputStream hostTwoDataOutputStream = new DataOutputStream(sockets.get(1).getOutputStream());
while (!Thread.currentThread().isInterrupted()) {
if (hostOneInputStream.available() > 0) {
String msg = hostOneDataInputStream.readUTF();
System.out.println("got message from host 1: " + msg);
hostTwoDataOutputStream.writeUTF(msg);
hostTwoDataOutputStream.flush();
System.out.println("message " + msg + " sent to host two");
}
if (hostTwoInputStream.available() > 0) {
String msg = hostTwoDataInputStream.readUTF();
System.out.println("got message from host 2: " + msg);
hostOneDataOutputStream.writeUTF(msg);
hostOneDataOutputStream.flush();
System.out.println("message " + msg + " sent to host one");
}
}
} catch (IOException e) {
e.printStackTrace();
}
First host (run it in separate thread or process)
try(Socket socket = new Socket("127.0.0.1", 5555);
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
while (!Thread.currentThread().isInterrupted()) {
dataOutputStream.writeUTF("1");
dataOutputStream.flush();
String msg = dataInputStream.readUTF();
System.out.println("got msg: " + msg);
TimeUnit.SECONDS.sleep(5);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
Second host (run it in separate thread or process)
try(Socket socket = new Socket("127.0.0.1", 5555);
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
while (!Thread.currentThread().isInterrupted()) {
String msg = dataInputStream.readUTF();
System.out.println("got msg: " + msg);
TimeUnit.SECONDS.sleep(5);
dataOutputStream.writeUTF("2");
dataOutputStream.flush();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}

Java while(true) loop executes only once inside thread

I am trying to implement a simple client-server application in Java.
Here is the code:
Client.java
public class Client implements Runnable {
private String hostName;
private int portNumber;
private String message;
private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
public Client(String hostName, int portNumber, String message) {
this.hostName = hostName;
this.portNumber = portNumber;
this.message = message;
}
public void connect() {
try {
socket = new Socket(hostName, portNumber);
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer.println(message);
} catch (UnknownHostException e) {
System.err.println("Could not resolve the host name '" + hostName + "'.");
} catch (IOException e) {
System.err.println("Could not get the I/O for the connection to '" + hostName + "'.");
}
}
private void listenForMessages() {
while (true) {
try {
System.out.println("In loop!");
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
public void run() {
connect();
listenForMessages();
}
}
Server.java
public class Server implements Runnable {
private int portNumber;
private String message;
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter writer;
private BufferedReader reader;
public Server(int portNumber, String message) {
this.portNumber = portNumber;
this.message = message;
}
private void listen() {
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.err.println(e.getMessage());
}
while (true) {
try {
clientSocket = serverSocket.accept();
writer = new PrintWriter(clientSocket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
writer.println(message);
} catch (IOException e) {
System.err.println(e.getMessage());
break;
}
}
}
public void run() {
listen();
}
}
And this is the main class:
public class Test {
public static void main(String[] args) {
Client client = new Client("localhost", 4444, "Hello from client!");
Server server = new Server(4444, "Hello from server!");
Thread serverThread = new Thread(server);
serverThread.start();
Thread clientThread = new Thread(client);
clientThread.start();
}
}
The logic of the code is simple: both the client and the server are waiting for messages inside a while(true) loop.
The while loop inside the server's listen method executes just fine. However, inside the listenForMessages method, the loop seems to be executed only once. I only see one "In loop" printed on the screen.
Can you figure out what the problem is?
Thank you in advance!
However, inside the listenForMessages method, the loop seems to be
executed only once. I only see one "In loop" printed on the screen.
Actually it is not because the loop is executed only once it is simply because reader.readLine() will make the current thread wait until it receives an entire line and here if you check the code of the Server, it reads first and it reads in an infinite loop as reader.readLine() will only return null at the end of the stream so when the socket will be closed in this case.
If you want to implement some kind of ping-pong between the client and the server, simply read then write on one side and write and read and the other side as next:
Client code:
public void connect() {
try {
socket = new Socket(hostName, portNumber);
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Could not resolve the host name '" + hostName + "'.");
} catch (IOException e) {
System.err.println(
"Could not get the I/O for the connection to '" + hostName + "'."
);
}
}
private void listenForMessages() {
while (true) {
try {
System.out.println("In loop!");
// Write the message for the server
writer.println(message);
// Read the message from the server
System.out.println(reader.readLine());
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
Server code:
while (true) {
try {
clientSocket = serverSocket.accept();
writer = new PrintWriter(clientSocket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while (true) {
// Read the message from the client
System.out.println(reader.readLine());
// Write the message for the client
writer.println(message);
}
} catch (IOException e) {
System.err.println(e.getMessage());
break;
}
}
Output:
In loop!
Hello from client!
Hello from server!
In loop!
Hello from client!
Hello from server!
...

Multithreading with client server program

I am trying to implement multi threading with a client/server program I have been working on. I need to allow multiple clients to connect to the server at the same time. I currently have 4 classes: a Client, a Server, a Protocol and a Worker to handle the threads. The following code is what I have for those classes:
SocketServer Class:
public class SocketServer {
public static void main(String[] args) throws IOException {
int portNumber = 9987;
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()));
) {
Thread thread = new Thread(new ClientWorker(clientSocket));
thread.start(); //start thread
String inputLine, outputLine;
// Initiate conversation with client
Protocol prot = new Protocol();
outputLine = prot.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = prot.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("quit"))
break;
}
} 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());
}
}
}
SocketClient Class:
public class SocketClient {
public static void main(String[] args) throws IOException
{
String hostName = "localhost";
int portNumber = 9987;
try (
Socket socket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("quit"))
break;
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
Protocol Class:
public class Protocol {
private static final int waiting = 0;
private static final int sentPrompt = 1;
private int status = waiting;
public String processInput(String theInput) {
String theOutput = null;
if (status == waiting) {
theOutput = "Please enter what you would like to retrieve: 'customer' or 'product' ";
status = sentPrompt;
}
else if ( status == sentPrompt ) {
if ( theInput.equalsIgnoreCase("product")) {
File f = new File("product.txt");
Scanner sc = null;
try {
sc = new Scanner(f);
} catch (FileNotFoundException ex) {
Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
}
while ( sc.hasNextLine() ) {
String line = sc.nextLine();
theOutput = "The current product entries are : " + line;
}
return theOutput;
}
else if ( theInput.equalsIgnoreCase("customer")) {
File f = new File("customer.txt");
Scanner sc = null;
try {
sc = new Scanner(f);
} catch (FileNotFoundException ex) {
Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
}
while ( sc.hasNextLine() ) {
String line = sc.nextLine();
theOutput = "The current customer entries are : " + line;
}
return theOutput;
}
else if ( theInput.equalsIgnoreCase("quit")) {
return "quit";
}
else {
return "quit";
}
}
return theOutput;
}
}
The ClientWorker Class:
public class ClientWorker implements Runnable {
private final Socket client;
public ClientWorker( Socket client ) {
this.client = client;
}
#Override
public void run() {
String line;
BufferedReader in = null;
PrintWriter out = null;
try {
System.out.println("Thread started with name:"+Thread.currentThread().getName());
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("in or out failed");
System.exit(-1);
}
while (true) {
try {
System.out.println("Thread running with name:"+Thread.currentThread().getName());
line = in.readLine();
//Send data back to client
out.println(line);
//Append data to text area
} catch (IOException e) {
System.out.println("Read failed");
System.exit(-1);
}
}
}
}
When I run the server and client, everything works fine as expected. Then when I try to run another client, it just hangs there and does not prompt the client to give a response. Any insight into what I am missing is greatly appreciated!
Your server code should address implement below functionalities.
Keep accepting socket from ServerSocket in a while loop
Create new thread after accept() call by passing client socket i.e Socket
Do IO processing in client socket thread e.g ClientWorker in your case.
Have a look at this article
Your code should be
ServerSocket serverSocket = new ServerSocket(portNumber);
while(true){
try{
Socket clientSocket = serverSocket.accept();
Thread thread = new ClientWorker(clientSocket);
thread.start(); //start thread
}catch(Exception err){
err.printStackTrace();
}
}
How many times does serverSocket.accept() get called?
Once.
That's how many clients it will handle.
Subsequent clients trying to contact will not have anybody listening to receive them.
To handle more clients, you need to call serverSocket.accept() in a loop.

Production ready Socket server in Java

There are many tutorials where explains about socket server/client sides, but all them are very trivial. Is there any tutorial for production ready code? I'm new in sockets. There is a client, that sends strings to server. I must create the server side. in server side I read string from client and after some manipulation saves them in db. I must response to client only IF I get string like "Error" for example. and if there are no any daya from client in 30 secs, I must close client connection, but server side must works. this is my test Client side:
public class ClientSideSocket2 {
public static void main(String[] args) {
String serverName = "localhost";
int port = 5555;
String line = "";
Socket client = null;
try {
System.out.println("Connecting to " + serverName + " on port " + port);
client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
PrintWriter toServer = new PrintWriter(client.getOutputStream(), true);
BufferedReader fromServer = new BufferedReader(new InputStreamReader(client.getInputStream()));
List<String> messages = new ArrayList<>();
for (int i = 0; i < 6; i++) {
messages.add("Message " + i+1);
}
messages.add("abc");
for (int i = 0; i < messages.size(); i++) {
toServer.println(messages.get(i));
if ((line = fromServer.readLine()) != null) {
System.out.println("Responce from server: " + line);
}
}
toServer.close();
fromServer.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
and my server side:
public class TRSServerInterface implements Runnable {
private ServerSocket serverSocket = null;
private Socket socket = null;
boolean runner = true;
String message = "";
public TRSServerInterface() {}
#Override
public void run() { // default run method of Thread class and Runnable interface
try {
int serverPort = 5555;
ServerSocket serverSocket = new ServerSocket(serverPort);
while(true) {
System.out.println("Waiting for connection...");
socket = serverSocket.accept();
System.out.println("Connected to " + socket.getRemoteSocketAddress());
//get the input and output streams
PrintWriter toClient = new PrintWriter(socket.getOutputStream(), true);
BufferedReader fromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do {
message = fromClient.readLine();
System.out.println("From client > " + message);
if (message.equals("abc")) {
toClient.println("Message from server");
}
else {
toClient.println("");
}
} while (!message.equals(""));
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
// try {
// objectOut.close();
// objectIn.close();
// socket.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}
is my solution corrent and how I can close connection with client if there are no any data in 30 secs.
There are several production ready frameworks that should be used instead of rolling your own. Socket timeouts can be used to control how long different operations are allowed to take before an exception is thrown.

Categories