I had stumbled upon a dead block when doing my assignment. It's a simple server and client program.
The details of this program is as follows;
Create a server class EncryptServer that listens for incoming connections. If there is a connection, accept it and create a thread EncryptServerSession to handle the input and output stream.
Create a thread class EncryptServerSession that takes in the input and output stream from the server class and process it.
Create a client class EncryptClient that connects to the server class and takes output stream from EncryptServerSession through EncryptServer.
Somehow the while true loop of the EncryptClient class is not working. I cannot seem to get into the loop. Is something wrong with my code? Thanks in advance.
EncryptServer
import java.net.*;
import java.io.*;
public class EncryptServer
{
public EncryptServer() throws IOException
{
ServerSocket serverSocket = new ServerSocket(1122);
System.out.println("Server started.");
while (true)
{
Socket conSocket = serverSocket.accept();
System.out.println("Client connected from " +
conSocket.getLocalAddress().getHostName());
Thread session = new
EncryptServerSession(conSocket.getInputStream(),
conSocket.getOutputStream());
session.start();
}
}
public static void main(String[] args)
{
try
{
EncryptServer server = new EncryptServer();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
EncryptServerSession
import java.net.*;
import java.io.*;
public class EncryptServerSession extends Thread
{
BufferedReader in;
Writer out;
public EncryptServerSession(InputStream inStream, OutputStream outStream)
{
Reader read = new InputStreamReader(inStream);
in = new BufferedReader(read);
out = new OutputStreamWriter(outStream);
}
public void strEncrypt()
{
try
{
String message = in.readLine();
out.write(message);
out.flush();
}
catch (Exception e)
{
}
}
public void run()
{
try
{
//System.out.println(in.readLine());
out.write("Please enter the message to be encrypted: ");
out.flush();
//strEncrypt();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
EncryptClient
import java.net.*;
import java.io.*;
public class EncryptClient
{
BufferedReader input, userTerm;
Writer output;
String line;
public EncryptClient() throws IOException
{
Socket clientSocket = new Socket("localhost", 1122);
Reader read = new InputStreamReader(clientSocket.getInputStream());
input = new BufferedReader(read);
userTerm = new BufferedReader(new InputStreamReader(System.in));
output = new OutputStreamWriter(clientSocket.getOutputStream());
/////////////// Somehow I cannot get into this loop, why? //////////
while (true)
{
System.out.println("test ");
System.out.println(input.readLine());
System.out.println("Enter message to be encrypted: ");
output.write(userTerm.readLine());
output.flush();
}
/////////////// Somehow I cannot get into this loop, why? //////////
}
public static void main(String[] args)
{
try
{
EncryptClient client = new EncryptClient();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
As I understand, you are trying to send a message to a server, do some logic, then send it back to the client. The above code seems to run well on my side. Here's what I've done:
run EncryptServer first. I expect this is the issue you are facing. or maybe your firewall isn't letting you listen on sockets.
in EncryptServerSession, You are reading lines but you aren't writing lines. either close the stream or write a new line after you finish.
...
out.write(message);
out.write("\r\n"); // write new line
out.flush();
...
} finally {
try {
out.close();
} catch (IOException e) {
}
}
OR
...
out.write(message);
out.write("\r\n"); // write new line
out.flush();
...
Related
I am currently working on a TCP Sockets program in Java in which two or more separate clients connect to a single server, and that server will send a message to both of these connected clients simultaneously.
I've tried to work through the code multiple times, but I can't quite seem to be able to have one message be sent to both clients.
Below is a reduced version of my entire code, condensed down to just the issue I'm having.
I've also included a video, just to save you the effort of having to copy and run my code!
[STREAMABLE LINK]
When one client is connected, I just have to write one message in the server, press send, and it shows up in the client.
When two clients are connected, I have to write two messages in the server and press send twice, and one message goes to one client and the other to the next client.
How can I make it so I only send one message from the server that goes to all clients?
I greatly appreciate any and all help.
SERVER CODE:
import java.io.*;
import java.net.*;
import java.util.*;
// Server class
class Server {
public class countLogic {
public static int client_count = 0;
}
public static void main(String[] args) {
System.out.println("[SERVER]");
ServerSocket server = null;
try {
server = new ServerSocket(1234);
server.setReuseAddress(true);
while (true) {
Socket client = server.accept();
countLogic.client_count++;
System.out.println("Client ("+countLogic.client_count+") connected: " + client.getInetAddress().getHostAddress());
ClientHandler clientSock = new ClientHandler(client);
new Thread(clientSock).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (server != null) {
try {
server.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket socket)
{
this.clientSocket = socket;
}
public void run()
{
PrintWriter out = null;
BufferedReader in = null;
try {
Scanner sc = new Scanner(System.in);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while (true) {
line = sc.nextLine();
out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
clientSocket.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
CLIENT CODE:
import java.io.*;
import java.net.*;
import java.util.*;
// Client class
class Client {
// driver code
public static void main(String[] args)
{
System.out.println("[CLIENT 1]");
try (Socket socket = new Socket("localhost", 1234)) {
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
System.out.println("Server: "+ in.readLine());
}
// closing the scanner object
sc.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
I was working on multi-client sockets and its working just fine, however it came to my mind on how to make the communication public by making the entered string being streamed to all clients.
e.g if there are lets say 3 clients A,B and C and client A sends "foo" to server, I want the server to stream "foo" to clients B and C as well.
The Server Module :
package multiclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String args[]) {
Socket s = null;
ServerSocket ss2 = null;
System.out.println("Server Listening......");
try {
ss2 = new ServerSocket(4445); // can also use static final PORT_NUM , when defined
} catch (IOException e) {
e.printStackTrace();
System.out.println("Server error");
}
while (true) {
try {
s = ss2.accept();
System.out.println("connection Established");
ServerThread st = new ServerThread(s);
st.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Connection Error");
}
}
}
}
class ServerThread extends Thread {
String line = null;
BufferedReader is = null;
PrintWriter os = null;
Socket s = null;
public ServerThread(Socket s) {
this.s = s;
}
public void run() {
try {
is = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
System.out.println("IO error in server thread");
}
try {
line = is.readLine();
while (line.compareTo("QUIT") != 0) {
os.println(line);
os.flush();
System.out.println("Response to Client : " + line);
line = is.readLine();
}
} catch (IOException e) {
line = this.getName(); //reused String line for getting thread name
System.out.println("IO Error/ Client " + line + " terminated abruptly");
} catch (NullPointerException e) {
line = this.getName(); //reused String line for getting thread name
System.out.println("Client " + line + " Closed");
} finally {
try {
System.out.println("Connection Closing..");
if (is != null) {
is.close();
System.out.println(" Socket Input Stream Closed");
}
if (os != null) {
os.close();
System.out.println("Socket Out Closed");
}
if (s != null) {
s.close();
System.out.println("Socket Closed");
}
} catch (IOException ie) {
System.out.println("Socket Close Error");
}
}//end finally
}
}
The Client Module:
package multiclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String args[]) throws IOException{
InetAddress address=InetAddress.getLocalHost();
Socket s1=null;
String line=null;
BufferedReader br=null;
BufferedReader is=null;
PrintWriter os=null;
try {
s1=new Socket(address, 4445); // 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");
}
System.out.println("Client Address : "+address);
System.out.println("Enter Data to echo Server ( Enter QUIT to end):");
String response=null;
try{
line=br.readLine();
while(line.compareTo("QUIT")!=0){
os.println(line);
os.flush();
response=is.readLine();
System.out.println("Server Response : "+response);
line=br.readLine();
}
}
catch(IOException e){
e.printStackTrace();
System.out.println("Socket read Error");
}
finally{
is.close();os.close();br.close();s1.close();
System.out.println("Connection Closed");
}
}
}
The server can keep a collection of all client sockets (until one is closed). When a client message arrives, server writes it to all client sockets.
There's a problem though, socket.write() is blocking, so if we do it in a loop, a slow client will block the rest of the clients. You can spawn a new thread to write to each individual socket, if there aren't too many clients.
In the blocking IO world, to implement a true full-duplex protocol, it is necessary for server to have two threads per client, one for read, one for write.
You may also try NIO if you are brave enough...
There are many examples. Search for chat server. One good one if you don't mind using a framework is Netty, check the SecureChat example for working code. It is a short and focused example.
Edit: the link takes you to the example code.
I suggest:
1. Keep the threads you create in an ArrayList
2. Create a method in Server called writeString and a lock
private final Lock mutex = new ReentrantLock(true);
private ArrayList<ServerThread> list = new ArrayList<ServerThread>();
public void writeString(ServerThread t,String s)
{
mutex.lock();
for(ServerThread th:list)
if(th!=null && th!=t) //different from the thread receiving the string
th.writeString(s); //send string to other threads
mutex.unlock();
}
3. in ServerThread class, implement writeString method and add a Lock
private final Lock mutex = new ReentrantLock(true);
public void writeString(String s)
{
mutex.lock();
os.println(s);
os.flush();
mutex.unlock();
}
4. Keep a reference to the main Server thread by modifying the constructor
//in ServerThread
private Server parent=null;
SeverThread(Socket s, Server parent)
{
this.parent=parent;
/*the rest of the code*/
}
//in Server
ServerThread st = new ServerThread(s,this);
st.start();
list.add(st);
When you read the string in ServerThread, call the Server writeString method in order to notify all the clients
parent.writeString(this,s); //calls the method we created at 2.
I am beginner to java and learning Socket Programming.I am using the basic chat server socket communication. I am having difficulty to print the server and client messages to the console window.
I would also implement this concept when i design my chat Server window UI and will update the char server intercommunication messages to my UI. I would like to know as how can I achieve that ?
Code for 1
Server.java
package ChApp;
import java.io.IOException;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
Socket s;
ServerSocket server = new ServerSocket(3900);
while(true)
{
s = server.accept();
ServerHandl handle1 = new ServerHandl(s);
Thread t1= new Thread(handle1);
t1.start();
System.out.println("Connection Succesful...");
server.close();
}
}
}
Serverhandl.java
package ChApp;
import java.io.*;
import java.net.*;
public class ServerHandl implements Runnable {
Socket s= null;
BufferedReader read;
PrintWriter write;
String msg="Server is sending a sample msg";
public ServerHandl(Socket s)
{
this.s = s;
}
public void run()
{
try {
write = new PrintWriter(s.getOutputStream());
write.println(msg);
read = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(read.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
read.close();
write.close();
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Client.java
package ChApp;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Socket s= null;
BufferedReader read;
PrintWriter write = null;
String h;
StringBuilder sb = new StringBuilder();
String sendmsg="Reply from client";
s= new Socket("localhost",3900);
read = new BufferedReader(new InputStreamReader(s.getInputStream()));
while((h=read.readLine())!=null)
{
sb.append(h);
}
write = new PrintWriter(s.getOutputStream(),true);
write.write(sendmsg);
write.flush();
s.close();
read.close();
write.close();
}
}
Your client is calling readLine() until it returns null, but your server is reading from the connection so it hasn't closed it yet, so the null will never arrive, so you're deadlocked.
Read one line from the server and then send a response, then close the socket. Have the server close the socket after it calls readLine().
hi i writ acode for client and for server and now i want to deliver the message between clint one to clint two and i dont succees to do this on server side i want to construct array for name and id and after i send message from the client side i can choose where or Which name the server deliver the message pleas help me to writ this
so this is the clint side
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class client {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader readerFromCommandLine = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
System.out.println("Say something:");
String userInput = readerFromCommandLine.readLine();
writer.println(userInput);
writer.flush();
String input = reader.readLine();
System.out.println("Got from server: "+input);
if (userInput.equalsIgnoreCase("bye")) {
break;
}
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
so now my code shuold by look like this ?
becaus i not yet can send from one client to client two
import java.awt.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class server {
public static void main(String[] args) {
ArrayList<Channel> my_clients = new ArrayList<Channel>();
ServerSocket ss = null;
try {
ss = new ServerSocket(7777);
while (true) {
//wait for a new client call - once got it, get the socket for
//that channel
System.out.println("Waiting for an incoming call");
Socket client = ss.accept();
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
//once the call has started read the client data
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
//my_client.writer("HELLO!");
}
}
//System.out.println("Accepted a new call");
//new Channel(client).start();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (ss != null) {
try {
ss.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
public static class Channel extends Thread {
private static int clientIndex = 0;
private int index;
private Socket socket = null;
public Channel(Socket socket) {
clientIndex++;
index = clientIndex;
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true) {
String input = reader.readLine();
System.out.println("Got from client "+index+": "+input);
//bye bye
if (input.equalsIgnoreCase("bye")) {
break;
}
writer.println("Gotcha");
writer.flush();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
}
String userInput = readerFromCommandLine.readLine();
BufferedReader.readLine() is a problem here. It is going to block your thread until input is received. This means communication can only ever go in one direction at a time, and can potentially get totally blocked if both clients are waiting.
DataFetcher can fix this problem; you can use it to listen in a separate Thread
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/
You half way there.
You created a Threaded Server were each connection from a client opens a thread. This thread then loops and waits for messages.
Think of these threads as you connected clients with their own objects / properties and their streams to write to and read from them.
So each time a clients connections you want to create their thread add it to some kind of list and start their thread. For example:
At the top of the class
List<Channel> my_clients = new List<Channel>();
In your while loop
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
Then when you want to send a message to a certain clients. You can loop all the Threads and look for one that has some kind of name or Unique Indentifier. For example:
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
my_client.write("HELLO!");
}
}
or in the same breath you could send a message to all your clients (Broadcast):
for(Channel my_client : my_clients) {
my_client.write("HELLO!");
}
remember to remove the clients when they disconnect too!
// Can't remember the precise exception correct my if I'm wrong!
catch(SocketException ex) {
my_clients.remove(this);
}
Note this expects that you some how authenticate and know the name of your client or supply them a UID which you reference when you are instructed to sent them something. And that the Channel class has the Write Method for connivance.
Hope that Help!
Here is the server code
package echoserver;
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) {
try {
//establish server socket
ServerSocket s = new ServerSocket(1981);
//Thread client connectionsincoming
while (true) {
//wait for incoming connection
Socket incoming = s.accept();
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package echoserver;
import java.net.*;
import java.util.*;
import java.io.*;
class ThreadedEchoHandler implements Runnable {
public ThreadedEchoHandler(Socket i) {
//initializing socket
incoming = i;
}
public void run() {
try {
try {
//recieve input stream from socket
InputStream inStream = incoming.getInputStream();
//recieve output stream from socket
OutputStream outStream = incoming.getOutputStream();
//Create a scanner from input stream
Scanner scan = new Scanner(inStream);
//Create printer writer from output stream and enabled auto flushing
PrintWriter out = new PrintWriter(outStream, true);
//prompt users on how to exit program soon as a long in into the server
out.println("Enter BYE to exit");
boolean done = false;
//while done is not true and scanner has next line loop
while (!done && scan.hasNextLine()) {
//reading text that came in from the socket
String line = scan.nextLine();
//On the server print the ip address of where the text is coming from and the text they typed
System.out.println("Recieved from " + incoming.getInetAddress().getHostAddress() + ": " + line);
//Echo back the text the client typed to the client
out.println("Echo: " + line);
//if they type BYE in caps terminate there connection and I also trimmed whitespaces
if (line.trim().equals("BYE")) {
done = true;
}
}
} //finally close the socket connection
finally {
incoming.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket incoming;
}
and here is the code for client
package client;
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws IOException {
PrintWriter out = null;
try {
Socket s = new Socket(InetAddress.getLocalHost(), 1981);
System.out.println("Connected to server on port 1981");
out = new PrintWriter(s.getOutputStream());
out.println("Hello");
s.close();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
}
Socktes are getting created successfully but when control goes to t.start() method call it is not calling run() method of ThreadedEchoHandler class.
Why is this happening? any idea?
The client writes "Hello" to the PrintWriter. So far, so good.
You may expect that the PrintWriter sends this text directly to the socket, but it doesn't. The documentation from the PrintWriter(OutputStream) constructor says that it creates a PrintWriter without automatic line flushing. This means that you have to call out.flush() whenever you want something to be actually sent.
Until you call out.flush() the text only exists in some internal buffer, and the server will not be able to see it.
My guess would be that the acept statement is blocking forever because no client is connecting to the server. You could wrap accept() in prints to prove or disprove.