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().
Related
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();
...
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.
When I send a String from my client to my server, the server always throws a
java.net.SocketException: Connection reset
If I send a Integer or other types other than a String, the exception would not have been thrown and the program runs absolutely fine.
Client Class:
import java.io.*;
import java.net.*;
public class TestingClient {
public static void main(String[] args) {
try {
Socket clientSocket = new Socket("localhost", 9998);
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
outputStream.flush();
outputStream.writeBytes("hello");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server Class:
import java.io.*;
import java.io.IOException;
import java.net.*;
public class TestingServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(9998);
Socket connectionToClient = serverSocket.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(connectionToClient.getInputStream()));
System.out.println(input.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Well, "hello" isn't a byte[]. On the client, write the String with DataOutputStream.writeUTF(String) and then flush(). Something like
outputStream.writeUTF("hello");
outputStream.flush();
and on the server, you can't use a BufferedReader. You need something like DataInputStream.readUTF()
DataInputStream dis = new DataInputStream(
connectionToClient.getInputStream());
System.out.println(dis.readUTF());
I am trying to launch server and client thread on the same process, but seems like the server thread is blocking the client thread (or vice versa). I'm not allowed to use any global variable between those threads(like semaphore or mutex, since the client and the server thread are launched by upper-class that I don't have the access of).
I found a similar question here , but it still use two different process (two main function).
Here is a sample of my code
The server code:
public class MyServer implements Runnable{
ServerSocket server;
Socket client;
PrintWriter out;
BufferedReader in;
public MyServer() throws IOException{
server = new ServerSocket(15243, 0, InetAddress.getByName("localhost"));
}
#Override
public void run() {
while(true){
try {
ArrayList<String> toSend = new ArrayList<String>();
System.out.println("I'll wait for the client");
client = server.accept();
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inputLine;
while((inputLine = in.readLine()) != null){
toSend.add("answering : "+inputLine);
}
for(String resp : toSend){
out.println(resp);
}
client.close();
out.close();
in.close();
} catch (IOException ex) {
}
}
}
}
And the client code:
public class MyClient implements Runnable{
Socket socket;
PrintWriter out;
BufferedReader in;
public MyClient(){
}
#Override
public void run() {
int nbrTry = 0;
while(true){
try {
System.out.println("try number "+nbrTry);
socket = new Socket(InetAddress.getByName("localhost"), 15243);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("Hello "+nbrTry+" !! ");
String inputLine;
while((inputLine = in.readLine()) != null){
System.out.println(inputLine);
}
nbrTry++;
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
}
}
}
And the supposed upper-class launching those thread:
public class TestIt {
public static void main(String[] argv) throws IOException{
MyServer server = new MyServer();
MyClient client = new MyClient();
(new Thread(server)).start();
(new Thread(client)).start();
}
}
It gives me as output:
I'll wait for the client
Try number 0
And it stuck here. What should I do to keep both server and client code running?
Thank you.
I'll be willing to take up your questions but basically you need to think through your logic a bit more carefully.
MyServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer implements Runnable {
ServerSocket server;
public MyServer() throws IOException {
server = new ServerSocket(15243, 0, InetAddress.getByName("localhost"));
}
#Override
public void run() {
while (true) {
try {
// Get a client.
Socket client = server.accept();
// Write to client to tell him you are waiting.
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
out.println("[Server] I'll wait for the client");
// Let user know something is happening.
System.out.println("[Server] I'll wait for the client");
// Read from client.
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inputLine = in.readLine();
// Write answer back to client.
out.println("[Server] Answering : " + inputLine);
// Let user know what it sent to client.
System.out.println("[Server] Answering : " + inputLine);
in.close();
out.close();
client.close();
} catch (Exception e) {
}
}
}
}
MyClient.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyClient implements Runnable {
Socket socket;
PrintWriter out;
BufferedReader in;
public MyClient() throws UnknownHostException, IOException {
}
#Override
public void run() {
int nbrTry = 0;
while (true) {
try {
// Get a socket
socket = new Socket(InetAddress.getByName("localhost"), 15243);
// Wait till you can read from socket.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine = in.readLine();
//inputLine contains the text '[Server] I'll wait for the client'. means that server is waiting for us and we should respond.
// Write to socket
out = new PrintWriter(socket.getOutputStream(), true);
out.println("[Client] Hello " + nbrTry + " !! ");
// Let user know you wrote to socket
System.out.println("[Client] Hello " + nbrTry++ + " !! ");
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
}
}
}
TestIt.java
import java.io.IOException;
public class TestIt {
public static void main(String[] argv) throws IOException {
MyServer server = new MyServer();
MyClient client = new MyClient();
(new Thread(server)).start();
(new Thread(client)).start();
}
}
Your client sends a string, then reads until the stream is exhausted:
while((inputLine = in.readLine()) != null){
BufferedReader.readLine() only returns null at the end of the stream, as I recall. On a stream, it will block until input is available
Your server receives until the stream is exhausted, then sends back its response.
After sending one line, you now have:
Your client waiting for a response.
Your server still waiting for more data from the client. But it doesn't send anything back until the end of the stream from the client (which never happens because the client is waiting for your response).
Hey I am implementing an electronic voting system based on client server chat.
When I run the server it runs without any problems but without printing as well and also the client. But as soon as I give the input to the client, it gives me the following exception and crashes. Here is the code of the server and the client. So what do u think I should do to start the engine?
package engine;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
public class Server {
ServerSocket server;
int port = 6000;
public Server() {
try {
server = new ServerSocket(6000);
} catch (IOException e) {
e.printStackTrace();
}
}
public void handleConnection(){
try {
while(true){
Socket connectionSocket;
connectionSocket = server.accept();
new ConnectionHandler(connectionSocket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.handleConnection();
}
}
class ConnectionHandler implements Runnable {
Socket connectionSocket;
Calendar votingStartTime;
Calendar votingEndTime;
boolean timeUp;
ObjectInputStream inFromClient;
ObjectOutputStream outToClient;
BufferedWriter outToFile;
BufferedReader inFromAdmin;
ArrayList<SingleClient> clients = new ArrayList<SingleClient>();
ArrayList<Candidate> candidates;
this is the part of the code the Exception comes from:
public ConnectionHandler(Socket socket) {
try {
this.connectionSocket = socket;
votingStartTime = new GregorianCalendar();
outToClient = new ObjectOutputStream(
connectionSocket.getOutputStream());
inFromClient = new ObjectInputStream(
connectionSocket.getInputStream());
inFromAdmin = new BufferedReader(new InputStreamReader(System.in));
startVotingSession();
Thread t = new Thread(this);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
and this is the client's main method the Exception as soon as i give the input:
public static void main(String[] args) throws Exception {
client c = new client();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input;
while(true){
input = br.readLine();
if(input.equals("0")){
c.register();
}else if(input.equals("1")){
c.login();
}else if(input.equals("2")){
c.listCandidates();
}else if(input.equals("3")){
c.vote();
}else if(input.equals("4")){
c.checkResults();
}else if(input.equals("5")){
c.checkFinalResults();
}else if(input.equals("6")){
c.logout();
}else {
break;
}
}
}
}
without seeing the relevant code, i would guess you are recreating the ObjectInputStream on an existing socket InputStream. you must create the object streams once per socket and re-use them until you are completely finished with the socket connection. also, you should always flush the ObjectOutputStream immediately after creation to avoid deadlock.