I'm trying to make a simple client-server networking program. Initially, I was not running the Server and Client objects concurrently. The command prompt would just get stuck on trying to run the program. I then decided to use threads. The result is the same; I believe I have to use wait() and notify() somewhere but I'm not able to get it.
The Server needs to run first, but it will have to wait for the incoming Socket reference before it can proceed. I believe some lines need to be shifted here and there before a wait-and-notify mechanism is implemented. Here's my code so far -:
package networking;
import java.net.*;
import java.io.*;
import java.util.Scanner;
class Server implements Runnable
{
ServerSocket ss;
Socket incoming;
public void run()
{
try
{
ss = new ServerSocket(8189);
incoming = ss.accept();
OutputStream outs = incoming.getOutputStream();
InputStream ins = incoming.getInputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
out.println("Hello, Bye to exit");
out.println("This is the server program");
out.println("It will echo client stuff");
boolean done = false;
while(!done && in.hasNextLine())
{
out.println("Echo: " + in.nextLine());
if(in.nextLine().trim().equals("Bye"))
done = true;
}
incoming.close();
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
class Client implements Runnable
{
Socket s;
public void run()
{
try
{
s = new Socket("localhost", 8189);
InputStream ins = s.getInputStream();
OutputStream outs = s.getOutputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
while(in.hasNextLine())
System.out.println("Client: " + in.nextLine());
out.println("Bye");
s.close();
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
public class Networking
{
public static void main(String... args)
{
Thread server = new Thread(new Server());
Thread client = new Thread(new Client());
server.start();
client.start();
}
}
Any tips and pointers would be much appreciated; I just need a nod(or more) in the right direction.
Your code for opening serve and client is correct. But the problem is in the while loop for reading or writing data it falls in a deadlock. Because after establishing the connection booth server and client is waiting for each other to write something in the stream. Try with this.
class Server implements Runnable {
ServerSocket ss;
Socket incoming;
public void run() {
try {
System.out.println("Server STarted");
ss = new ServerSocket(8189);
incoming = ss.accept();
System.out.println("Client accepted");
OutputStream outs = incoming.getOutputStream();
InputStream ins = incoming.getInputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
out.println("Hello, Bye to exit");
out.println("This is the server program");
out.println("It will echo client stuff");
boolean done = false;
while (!done) { // && in.hasNextLine()
// out.println("Echo: " + in.nextLine());
// if (in.nextLine().trim().equals("Bye")) {
// done = true;
// }
out.println("TEsting from server");
}
incoming.close();
System.out.println("End server");
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
Related
I want to edit this code, so it could accept more client join on my server. This server is just used to accept one client's connection, and it can send, and receive messages. But I want to make it a "Multiplayer" Server. Many clients connected to one server. Here's the Server side code, and the Client side code:
I would really appreciate your help!
My Server Code:
import java.net.*;
import java.lang.*;
public class RecordAppServer {
public static void main(String[] args) throws IOException {
final int port = 8136;
System.out.println("Server waiting for connection on port "+port);
ServerSocket ss = new ServerSocket(port);
Socket clientSocket = ss.accept();
System.out.println("Recieved connection from "+clientSocket.getInetAddress()+" on port "+clientSocket.getPort());
//create two threads to send and recieve from client
RecieveFromClientThread recieve = new RecieveFromClientThread(clientSocket);
Thread thread = new Thread(recieve);
thread.start();
SendToClientThread send = new SendToClientThread(clientSocket);
Thread thread2 = new Thread(send);
thread2.start();
}}
class RecieveFromClientThread implements Runnable
{
Socket clientSocket=null;
BufferedReader brBufferedReader = null;
public RecieveFromClientThread(Socket clientSocket)
{
this.clientSocket = clientSocket;
}//end constructor
public void run() {
try{
brBufferedReader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
String messageString;
while(true){
while((messageString = brBufferedReader.readLine())!= null){//assign message from client to messageString
if(messageString.equals("EXIT"))
{
break;//break to close socket if EXIT
}
System.out.println("From Client: " + messageString);//print the message from client
//System.out.println("Please enter something to send back to client..");
}
this.clientSocket.close();
System.exit(0);
}
}
catch(Exception ex){System.out.println(ex.getMessage());}
}
}//end class RecieveFromClientThread
class SendToClientThread implements Runnable
{
PrintWriter pwPrintWriter;
Socket clientSock = null;
public SendToClientThread(Socket clientSock)
{
this.clientSock = clientSock;
}
public void run() {
try{
pwPrintWriter =new PrintWriter(new OutputStreamWriter(this.clientSock.getOutputStream()));//get outputstream
while(true)
{
String msgToClientString = null;
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));//get userinput
msgToClientString = input.readLine();//get message to send to client
pwPrintWriter.println(msgToClientString);//send message to client with PrintWriter
pwPrintWriter.flush();//flush the PrintWriter
//System.out.println("Please enter something to send back to client..");
}//end while
}
catch(Exception ex){System.out.println(ex.getMessage());}
}//end run
}//end class SendToClientThread
My Client Code:
import java.io.*;
import java.net.*;
public class RecordAppClient {
public static void main(String[] args)
{
try {
Socket sock = new Socket("192.168.0.2",8136);
SendThread sendThread = new SendThread(sock);
Thread thread = new Thread(sendThread);thread.start();
RecieveThread recieveThread = new RecieveThread(sock);
Thread thread2 =new Thread(recieveThread);thread2.start();
} catch (Exception e) {System.out.println(e.getMessage());}
}
}
class RecieveThread implements Runnable
{
Socket sock=null;
BufferedReader recieve=null;
public RecieveThread(Socket sock) {
this.sock = sock;
}//end constructor
public void run() {
try{
recieve = new BufferedReader(new InputStreamReader(this.sock.getInputStream()));//get inputstream
String msgRecieved = null;
while((msgRecieved = recieve.readLine())!= null)
{
System.out.println("From Server: " + msgRecieved);
//System.out.println("Please enter something to send to server..");
}
}catch(Exception e){System.out.println(e.getMessage());}
}//end run
}//end class recievethread
class SendThread implements Runnable
{
Socket sock=null;
PrintWriter print=null;
BufferedReader brinput=null;
public SendThread(Socket sock)
{
this.sock = sock;
}//end constructor
public void run(){
try{
if(sock.isConnected())
{
System.out.println("Client connected to "+sock.getInetAddress() + " on port "+sock.getPort());
this.print = new PrintWriter(sock.getOutputStream(), true);
while(true){
//System.out.println("Type your message to send to server..type 'EXIT' to exit");
brinput = new BufferedReader(new InputStreamReader(System.in));
String msgtoServerString=null;
msgtoServerString = brinput.readLine();
this.print.println(msgtoServerString);
this.print.flush();
if(msgtoServerString.equals("EXIT"))
break;
}//end while
sock.close();}}catch(Exception e){System.out.println(e.getMessage());}
}//end run method
}//end class
You'll need to implement a multithreaded server.
The general structure will be the following:
while(true) {
1) Wait for client requests (Socket client = server.accept();)
2) Create a thread with the client socket as parameter
a) The new thread creates I/O streams (just like youre doing
with the PrintWriter and BufferedReader objects)
b) Communicate with client (in your example -
brBufferedReader.readLine())
3) Remove thread once the service is provided.
}
I suggest you take a look at the Oracle documentation:
https://www.oracle.com/technetwork/java/socket-140484.html#multi
This might also be useful:
http://tutorials.jenkov.com/java-multithreaded-servers/multithreaded-server.html
I'm new with Java and I'm trying to learn threads and socket. So decide to make simple client-server application following official java tutorial. My idea is simple - server wait for connection, if appears, it makes new thread with new socket, input and output. Client side -> make connection; new thread with socket, input, output and stdIn (to read line and after that send it to the server). But something is wrong (don't have any idea why) with my code. The connection is established, there's no exceptions. Could someone explain why doesn't work and how to fix it? Also could you have any suggestions about the code (probably it's not with best practices and things like that):
Client side:
public class Client {
private BufferedReader reader;
private Socket sock;
private PrintWriter writer;
public static void main(String[] args) {
Client client = new Client();
client.go();
}
public void go() {
setUpNetworking();
}
private void setUpNetworking() {
try{
sock = new Socket("127.0.0.1", 5000);
System.out.println("Network established");
ServerThread serverThread= new ServerThread(sock);
serverThread.start();
System.out.println("Type your message: ");
} catch (IOException e) {
System.out.println("Problem with establishing the network: " + e);
}
}
class ServerThread extends Thread {
Socket socket;
PrintWriter out;
BufferedReader in;
BufferedReader stdIn;
ServerThread(Socket socket) {
this.socket = socket;
try{
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
}catch (IOException e) {
System.out.println("Problem with trying to read/write to server: " + e);
}
}
#Override
public void run() {
String fromServer;
String fromClient;
while(true){
try{
if((fromServer = in.readLine()) != null) System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null) out.println(fromClient);
}catch(Exception e) {
System.out.println("msg exception: " + e);
}
}
}
}
}
Server side:
public class Server {
//Run server until keepGoing = false
private boolean keepGoing = true;
public static void main(String[] args) {
Server server = new Server();
server.go();
}
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000);
while(keepGoing) {
Socket clientSocket = serverSocket.accept();
ClientThread t = new ClientThread(clientSocket);
t.start();
}
} catch (IOException e) {
System.out.println("Problem with socket/network: " + e);
}
}
class ClientThread extends Thread {
Socket clientSocket;
PrintWriter out;
BufferedReader in;
ClientThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try{
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
System.out.println("Problem with creating in/out: " + e);
}
}
#Override
public void run() {
String message;
while(keepGoing) {
try{
message = in.readLine();
out.println(message);
System.out.println(message);
} catch (IOException e){
System.out.println("Exception while try to read line: " + e);
}
}
}
}
}
PS I've changed a bit the code - instead of made ClientThread Class, I made new runnable class and pass that variable to thread class. Inspired by this question: "implements Runnable" vs. "extends Thread".
I think the problem is that both server and client are waiting for any input. Server:
message = in.readLine();
Client:
if((fromServer = in.readLine()) != null)
System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null)
out.println(fromClient);
But the client code already blocks on the fromServer = in.readLine() part, so it never gets to read from standard in, and thus nothing will be sent out to the server.
You could move your attempt to read from standard in to the setUpNetworking method, right after the System.out.println("Type your message: ");. Build a loop there which you exit if the user types "exit" or "quit" or something like that:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String read = "";
do {
read = stdIn.readLine();
System.out.println("Read from stdin: " + read);
serverThread.send(read);
}
while (!read.equals("exit"));
The ServerThread.send() method is simple:
void send(String string) {
System.out.println("Sending to server: " + string);
out.println(string);
}
However, to make it work, you either have to flush the stream manually after writing to out, or use the following constructor:
out = new PrintWriter(socket.getOutputStream(), true);
See the PrintWriter's JavaDoc: True means auto-flush on newline.
I tested this setup and it worked for me. I was able to send something from the client to the server.
However, this is only the first step. I would implement both reading and writing as separate threads, for both client and server. And there is no graceful shutdown of sockets implemenented yet. A more complete yet simple example can be found on Oracle.
I am very new to sockets and was hoping someone could help me. I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works. The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept(); even though im pretty sure the sender is still sending messages
Can anyone see what i might be doing wrong here please?
Thanks
public class Sender {
Socket server = null;
DataInputStream inp = null;
PrintStream outp = null;
public Sender(){
server = new Socket("127.0.0.1" , 3456);
outp = new PrintStream(server.getOutputStream());
}
private void connectAndSendToServer(String message) {
outp = new PrintStream(server.getOutputStream());
outp.print(message + "\n");
outp.flush();
}
}
Receiver class
public class Receive{
public String receiveMessage(int port) {
String message= null;
ServerSocket listener = null;
Socket client = null;
try{
listener = new ServerSocket(port);
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
return br.readLine();
}
...
finally{
try {
if(client!=null && listener!=null){
client.close();
listener.close();
}
}
catch (IOException e) {
}
}
return message;
}
}
This because a ServerSocket is used as an entry point for a normal Socket. accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket. It sits there and waits for a new connection to spawn a new Socket which is then used for data.
This means that while receiving messages you should call just readLine() to read from the specific Socket. Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.
Socket socket = serverSocket.accept();
ClientThread thread = new ClientThread(socket);
class ClientThread extends Thread {
Socket socket;
public void run() {
while (!closed) {
String line = reader.readLine();
...
}
}
You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.
You are not using ServerSocket correctly. You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection. Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.
Something like (< condition met > is pseudo-code defines your condition to accept new connections):
while(< condition met >) {
try {
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = br.readLine();
//do something with str
} finally {
//close client socket
}
}
Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.
Try this basic Chatting Server written by me. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
// ///----------------------------------------Instance Variable Fields
ServerSocket ss = null;
Socket incoming = null;
// ///----------------------------------------Instance Variable Fields
// ///---------------------------------------- static Variable Fields
public static ArrayList<Socket> socList = new ArrayList<Socket>();
// ///---------------------------------------- static Variable Fields
public void go() {
try {
ss = new ServerSocket(25005);
while (true) {
incoming = ss.accept();
socList.add(incoming);
System.out.println("Incoming: " + incoming);
new Thread(new ClientHandleKaro(incoming)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandleKaro implements Runnable {
InputStream is = null;
OutputStream os = null;
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
boolean isDone = false;
Socket sInThread = null;
public ClientHandleKaro(Socket sxxx) {
this.sInThread = sxxx;
}
#Override
public void run() {
if (sInThread.isConnected()) {
System.out.println("Welcamu Clienta");
System.out.println(socList);
}
try {
is = sInThread.getInputStream();
System.out.println("IS: " + is);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = sInThread.getOutputStream();
pw = new PrintWriter(os, true);
String s = new String();
while ((!isDone) && (s = br.readLine()) != null) {
String[] asx = s.split("-");
System.out.println("On Console: " + s);
// pw.println(s);
Thread tx = new Thread(new ReplyKaroToClient(s,
this.sInThread));
tx.start();
if (asx[1].trim().equalsIgnoreCase("BYE")) {
System.out.println("I am inside Bye");
isDone = true;
}
}
} catch (IOException e) {
System.out.println("Thanks for Chatting.....");
} finally {
try {
Thread tiku = new Thread(new ByeByeKarDo(sInThread));
tiku.start();
try {
tiku.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Accha to hum Chalte hain !!!");
System.out.println(socList);
br.close();
pw.close();
sInThread.close();
} catch (IOException e) {
}
}
}
}
class ReplyKaroToClient implements Runnable {
public String mString;
public Socket mSocket;
public ReplyKaroToClient(String s, Socket sIn) {
this.mString = s;
this.mSocket = sIn;
}
#Override
public void run() {
for (Socket sRaW : socList) {
if (mSocket.equals(sRaW)) {
System.out.println("Mai same hun");
continue;
} else {
try {
new PrintWriter(sRaW.getOutputStream(), true)
.println(mString);
} catch (IOException e) {
System.out.println("Its in Catch");
}
}
}
}
}
class ByeByeKarDo implements Runnable {
Socket inCom;
public ByeByeKarDo(Socket si) {
this.inCom = si;
}
#Override
public void run() {
try {
new PrintWriter(inCom.getOutputStream(), true)
.println("You have Logged Out of Server... Thanks for your Visit");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().go();
}
}
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.
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.