I'm trying to establish a two-way communication in Java. For that I created a simple client-server program (I'm not even sure if that's the right approach because both of them are considered client!). My requirement is that once the two program are connected, they should maintain the connection, and be able to send messages once in a while. However, currently my socket terminates once it had sent the data (client's main method has been executed).
How can I maintain the connection, so to make it persistent?
P.S: Is there any ways to make it work in an asynchronous way that might be more suitable for my requirements (I don't want the server always looping inside a while)?
Client:
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class EchoClient2 {
String serverHostname = new String("127.0.0.1");
BufferedReader stdIn;
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
public void open(){
System.out.println("Attemping to connect to host " + serverHostname
+ " on port 9999.");
try {
echoSocket = new Socket(serverHostname, 9999);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: "
+ serverHostname);
}
}
public void send(String s){
out.println(s);
}
public String receive(){
String result = "";
try {
result = in.readLine();
System.out.println("client received: "+result);
if(result==null)
return "0";
} catch (IOException e) {
}
return result;
}
public static void main(String[] args) {
EchoClient2 ec = new EchoClient2();
ec.open();
ec.send("1");
ec.receive();
}
}
Server:
package test;
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 EchoServer extends Thread {
protected Socket clientSocket;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(9999);
System.out.println("Connection Socket Created");
try {
while (true) {
System.out.println("Waiting for Connection");
new EchoServer(serverSocket.accept());
}
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
} catch (IOException e) {
System.err.println("Could not listen on port: 9999.");
System.exit(1);
} finally {
try {
serverSocket.close();
} catch (IOException e) {
System.err.println("Could not close port: 9999.");
System.exit(1);
}
}
}
private EchoServer(Socket clientSoc) {
clientSocket = clientSoc;
start();
}
public void run() {
System.out.println("New Communication Thread Started");
try {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Server received: " + inputLine);
out.println(inputLine);
if (inputLine.equals("Bye."))
break;
}
// out.close();
// in.close();
// clientSocket.close();
} catch (IOException e) {
System.err.println("Problem with Communication Server");
System.exit(1);
}
}
}
First of all sorry for the late answer. I am also stuck in this java socket programming. I also want to open a socket and keep it open for communication between client and server. And after searching and reading many books and articles I found the easiest solution. You can use android life cycles for your work in
Open the socket on onStart method
protected void onStart() {
super.onStart();
new Thread(new Runnable() {
#Override
public void run() {
try {
client = new Socket(ip,Integer.valueOf(port) );
client.setKeepAlive(true);
dataInputStream = new DataInputStream(client.getInputStream());
// readdata=readdata+" "+dataInputStream.readUTF();
readdata=dataInputStream.readUTF();
}
catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
and close the socket on onStop method
protected void onStop() {
super.onStop();
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Related
I want to create simple communicator with one server and few clients who could connect and send data to it. It works fine without any threads, with only one client, but once i try to incorporate concurrency it doesn't work. From client perspective there is some connection, I can send data, but there is no sign of receiving that data on server. Here is the server class:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class MyServerSocket implements Runnable
{
private ServerSocket serverSocket;
public MyServerSocket() throws Exception
{
Random generator = new Random();
this.serverSocket = new ServerSocket(generator.nextInt(65000 - 60000) + 60000, 50, InetAddress.getByName("192.168.0.105"));
}
public InetAddress getSocketIPAddress()
{
return this.serverSocket.getInetAddress();
}
public int getPort()
{
return this.serverSocket.getLocalPort();
}
public void run()
{
while (true)
{
System.out.println("Running a thread");
try
{
String data = null;
Socket client = this.serverSocket.accept();
String clientAddress = client.getInetAddress().getHostName();
System.out.println("Connection from: " + clientAddress);
System.out.println("Here I am");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String message = "";
while ((data = in.readLine()) != null && data.compareToIgnoreCase("quit") != 0)
{
message = ("\r\nMessage from " + clientAddress + ": " + data);
System.out.println(message);
out.write(message);
}
} catch (Exception e)
{
System.out.println("Something went wrong");
} finally
{
try
{
serverSocket.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
Server main:
import java.lang.Thread;
public class Main
{
public static void main(String[] args)
{
try
{
MyServerSocket socket = new MyServerSocket();
Runnable runnable = new MyServerSocket();
System.out.println("Port number: " + socket.getPort() + " IP address: " + socket.getSocketIPAddress());
Thread thread = new Thread(runnable);
thread.start();
}catch (Exception e)
{
e.printStackTrace();
}
}
}
Client class:
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class ClientSocket
{
private Socket socket;
private Scanner scanner;
ClientSocket(InetAddress serverAddress, int serverPort) throws Exception
{
this.socket = new Socket(serverAddress, serverPort);
this.scanner = new Scanner(System.in);
}
public void sendData() throws Exception
{
String data;
System.out.println("Please type in the message. If you want to terminate the connection, type Quit");
PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true);
do
{
data = scanner.nextLine();
out.println(data);
out.flush();
}while(data.compareToIgnoreCase("quit") != 0);
out.println();
}
}
Client main:
import java.net.InetAddress;
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int port;
System.out.println("Provide port at which you will communicate with the server");
port = scanner.nextInt();
try
{
ClientSocket socket1 = new ClientSocket(InetAddress.getByName("192.168.0.105"), port);
socket1.sendData();
}catch(Exception e)
{
System.out.println("Could not connect to the server.");
}
}
}
Server somehow stops its working when is about to accept the client connection, while client works fine and seem to be connected to the server.
In server side, once you accept a client connection, you should new a thread to process this connection:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class MyServerSocket implements Runnable {
private ServerSocket serverSocket;
public MyServerSocket() throws Exception {
Random generator = new Random();
this.serverSocket = new ServerSocket(generator.nextInt(65000 - 60000) + 60000, 50, InetAddress.getByName("192.168.0.105"));
}
public InetAddress getSocketIPAddress() {
return this.serverSocket.getInetAddress();
}
public int getPort() {
return this.serverSocket.getLocalPort();
}
public void run() {
while (true) {
System.out.println("Running a thread");
try(Socket client = this.serverSocket.accept()) {
// new thread to process this client
new Thread(() -> {
try {
String data = null;
String clientAddress = client.getInetAddress().getHostName();
System.out.println("Connection from: " + clientAddress);
System.out.println("Here I am");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String message = "";
while (true) {
if (!((data = in.readLine()) != null && data.compareToIgnoreCase("quit") != 0)) break;
message = ("\r\nMessage from " + clientAddress + ": " + data);
System.out.println(message);
out.write(message);
}
} catch (IOException e) {
System.out.println("Something went wrong");
}
}).start();
} catch (Exception e) {
System.out.println("Something went wrong");
}
}
}
}
Ok, somehow I solved that problem, but still I need to understand how does it work:
Accepting connection inside try block, without finally block (nor try with resources) so socket is opened all the time.
Modified main method so there is no threads or runnable objects at all in it. The whole process is done within the class:
Code:
public class Main
{
public static void main(String[] args)
{
try
{
MyServerSocket socket = new MyServerSocket();
System.out.println("Port number: " + socket.getPort() + " IP address: " + socket.getSocketIPAddress());
socket.run();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
If anyone could point me out mistakes that are still in this final version of code I'll be grateful.
How do you handle multiple client to connect to one server? I have this LogServer.java
import javax.net.ssl.*;
import javax.net.*;
import java.io.*;
import java.net.*;
public class LogServer {
private static final int PORT_NUM = 5000;
public static void main(String args[]) {
ServerSocketFactory serverSocketFactory =
ServerSocketFactory.getDefault();
ServerSocket serverSocket = null;
try {
serverSocket =
serverSocketFactory.createServerSocket(PORT_NUM);
} catch (IOException ignored) {
System.err.println("Unable to create server");
System.exit(-1);
}
System.out.printf("LogServer running on port: %s%n", PORT_NUM);
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(is, "US-ASCII"));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException exception) {
// Just handle next request.
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException ignored) {
}
}
}
}
}
}
and an embedded applet with part of the code like this e.g
import java.io.*;
import java.util.logging.*;
public class LogTest
{
private static Logger logger = Logger.getAnonymousLogger();
public static void main(String argv[]) throws IOException
{
Handler handler = new SocketHandler("localhost", 5000);
logger.addHandler(handler);
logger.log(Level.SEVERE, "Hello, World");
logger.log(Level.SEVERE, "Welcome Home");
logger.log(Level.SEVERE, "Hello, World");
logger.log(Level.SEVERE, "Welcome Home");
}
}
now the question is if I run "java LogServer" on the server, it will open the application and waiting for input stream and if I open my site, it will start streaming the log. But if I open one more using other computer/network, the second site does not log the stream. seems like it's because the first one still bind to port 5000.
How do I handle this?
How does socket actually work with multiple client / one server?
For every client you need to start separate thread. Example:
public class ThreadedEchoServer {
static final int PORT = 1978;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new thread for a client
new EchoThread(socket).start();
}
}
}
and
public class EchoThread extends Thread {
protected Socket socket;
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
}
public void run() {
InputStream inp = null;
BufferedReader brinp = null;
DataOutputStream out = null;
try {
inp = socket.getInputStream();
brinp = new BufferedReader(new InputStreamReader(inp));
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
return;
}
String line;
while (true) {
try {
line = brinp.readLine();
if ((line == null) || line.equalsIgnoreCase("QUIT")) {
socket.close();
return;
} else {
out.writeBytes(line + "\n\r");
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
You can also go with more advanced solution, that uses NIO selectors, so you will not have to create thread for every client, but that's a bit more complicated.
This is the echo server handling multiple clients... Runs fine and good using Threads
// echo server
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_X_Client {
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
}
}
Also here is the code for the client.. Just execute this code for as many times as you want to create multiple client..
// A simple Client Server Protocol .. Client for Echo Server
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 NetworkClient {
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");
}
}
}
I guess the problem is that you need to start a separate thread for each connection and call serverSocket.accept() in a loop to accept more than one connection.
It is not a problem to have more than one connection on the same port.
See O'Reilly "Java Cookbook", Ian Darwin - recipe 17.4 Handling Multiple Clients.
Pay attention that accept() is not thread safe, so the call is wrapped within synchronized.
64: synchronized(servSock) {
65: clientSocket = servSock.accept();
66: }
Here is code for Multiple Client to one Server Working Fine ..
Give it a try :)
Server.java:
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
class Multi extends Thread{
private Socket s=null;
DataInputStream infromClient;
Multi() throws IOException{
}
Multi(Socket s) throws IOException{
this.s=s;
infromClient = new DataInputStream(s.getInputStream());
}
public void run(){
String SQL=new String();
try {
SQL = infromClient.readUTF();
} catch (IOException ex) {
Logger.getLogger(Multi.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Query: " + SQL);
try {
System.out.println("Socket Closing");
s.close();
} catch (IOException ex) {
Logger.getLogger(Multi.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class Server {
public static void main(String args[]) throws IOException,
InterruptedException{
while(true){
ServerSocket ss=new ServerSocket(11111);
System.out.println("Server is Awaiting");
Socket s=ss.accept();
Multi t=new Multi(s);
t.start();
Thread.sleep(2000);
ss.close();
}
}
}
Client1.java:
import java.io.DataOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
public class client1 {
public static void main(String[] arg) {
try {
Socket socketConnection = new Socket("127.0.0.1", 11111);
//QUERY PASSING
DataOutputStream outToServer = new DataOutputStream(socketConnection.getOutputStream());
String SQL="I am client 1";
outToServer.writeUTF(SQL);
} catch (Exception e) {System.out.println(e); }
}
}
Client2.java
import java.io.DataOutputStream;
import java.net.Socket;
public class client2 {
public static void main(String[] arg) {
try {
Socket socketConnection = new Socket("127.0.0.1", 11111);
//QUERY PASSING
DataOutputStream outToServer = new DataOutputStream(socketConnection.getOutputStream());
String SQL="I am Client 2";
outToServer.writeUTF(SQL);
} catch (Exception e) {System.out.println(e); }
}
}
I'm writing simple software, PC is socket server, android connects to it and then whatever I write on keyboard on PC, android gets it and simply logs.
Android code:
package com.example.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket("192.168.2.3", 4444);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
Log.e("j", "Don't know about host: JANIPC.");
System.exit(1);
} catch (IOException e) {
Log.e("j", "Can't connect to Jani-PC");
System.exit(1);
}
try {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
//out.println(userInput);
Log.e("j", "echo: " + in.readLine());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here goes my PC Java code:
package jani.study.socketserver;
import java.io.*;
import java.net.*;
/**
*
* #author Jani
*/
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
System.in));
String inputLine;
System.out.println("Connected!");
/*while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}*/
Thread.sleep(1000);
out.println("1");
Thread.sleep(1000);
out.println("2");
Thread.sleep(1000);
out.println("3");
Thread.sleep(1000);
out.println("4");
Thread.sleep(1000);
out.println("5");
Thread.sleep(1000);
out.println("6");
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
In Android debugger, I only get every second request, I mean, I only get:
echo: 2
echo: 4
echo: 6
what am I doing wrong? please help
You're using two BufferedReaders, one in and one stdIn both reading from the socket. You are consuming the current line first in the while loop, then consuming the next in the Log statement.
Try this:
Log.e("j", "echo: " + userInput);
You call readLine twice in the reader and only print the results of every other call to readLine. You probably want:
while ((userInput = stdIn.readLine()) != null) {
//out.println(userInput);
Log.e("j", "echo: " + userInput);
}
In this code I can correctly receive a request using BufferedReader inClient, created on the client socket.
Then I send the request to the server and I see the server gets it.
But then, when I try to read the reply from the server (using BufferedReader inServer on the socket of the server), it always ends in IOException: Impossible read from server.
I am referring to the block ################
Do you know any possible reasons?
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ProxyMain {
public static void main(String argv[]) {
int proxyPort = 55554;
String proxyAddr = "127.0.0.1";
ServerSocket proxySocket = null;
try {
proxySocket = new ServerSocket(proxyPort, 50, InetAddress.getByName("127.0.0.1"));
}
catch (Exception e) {
System.err.println("Impossible to create socket server!");
System.out.flush();
System.exit(1);
}
System.out.printf("Proxy active on port: %d and on address %s\n", proxyPort, proxySocket.getInetAddress());
System.out.println();
while (true) {
Socket client = null;
Socket sockServ = null;
BufferedReader inClient = null;
PrintWriter outClient = null;
BufferedReader inServer = null;
PrintWriter outServer = null;
String request = new String();
String tmp = new String();
String reply = new String();
String tmpReply = new String();
try {
client = proxySocket.accept();
System.out.println("Connected to: ");
System.out.println(client.getInetAddress().toString());
System.out.printf("On port %d\n", client.getPort());
System.out.println();
inClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
outClient = new PrintWriter(client.getOutputStream(), true);
}
/*catch (IOException e) {
System.err.println("Couldn't get I/O for connection accepted");
System.exit(1);
}*/
catch (Exception e) {
System.out.println("Error occurred!");
System.exit(1);
}
System.out.println("Received request:");
try{
for (int i = 0; i<2; i++) {
tmp = inClient.readLine();
request = request + tmp;
}
inClient.close();
}
catch (IOException ioe) {
System.err.println("Impossible to read mhttp request!");
System.exit(1);
}
System.out.println(request);
System.out.println();
try {
sockServ = new Socket("127.0.0.1", 55555);
outServer = new PrintWriter(sockServ.getOutputStream(), true);
inServer = new BufferedReader(new InputStreamReader(sockServ.getInputStream()));
}
catch (UnknownHostException e) {
System.err.println("Don't know about host: 127.0.0.1:55555");
System.exit(1);
}
catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: 127.0.0.1:55555");
System.exit(1);
}
outServer.println(request);
outServer.close();
try {
#################################################
while ((tmpReply = inServer.readLine()) != null) {
System.out.println(tmpReply);
reply = reply + tmpReply;
}
inServer.close();
sockServ.close();
}
catch (IOException ioe) {
System.err.println("Impossible to read from server!");
System.exit(1);
}
outClient.println(reply);
outClient.close();
try {
client.close();
}
catch (IOException ioe) {
System.err.printf("Impossible to close connection with %s:%d\n", client.getInetAddress().toString(), client.getPort());
}
}
}
}
UPDATE:
It seems that if I do:
boolean res = inServer.ready();
it always return false.
So Server is not ready to send the reply but this is strange...with my Project in C e Python it worked immediately. Why should java be different?
When you close outServer, you close the underlying socket. if you just want to close the output and keep the input open, you need to use Socket.shutdownOutput(). note, you have the same problem when you close inClient.
This works, maybe you can get some ideas from it...
ChatServer - broadcasts to all connected clients
In one command prompt: java ChartServer
In another: java ChatClient localhost (or the ip address of where the server is running)
And another: java ChatClient localhost (or the ip address of where the server is running)
Start chatting in the client windows.
Server like this...
// xagyg wrote this, but you can copy it
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer {
public static List list = new ArrayList();
public static void main(String[] args) throws Exception {
ServerSocket svr = new ServerSocket(4444);
System.out.println("Chat Server started!");
while (true) {
try {
Socket s = svr.accept();
synchronized(list) {
list.add(s);
}
new Handler(s, list).start();
}
catch (IOException e) {
// print out the error, but continue!
System.err.println(e);
}
}
}
}
class Handler extends Thread {
private Socket s;
private String ipaddress;
private List list;
Handler (Socket s, List list) throws Exception {
this.s = s;
ipaddress = s.getInetAddress().toString();
this.list = list;
}
public void run () {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String message;
//MyDialog x = (MyDialog)map.get(ipaddress.substring(1));
while ((message = reader.readLine()) != null) {
if (message.equals("quit")) {
synchronized(list) {
list.remove(s);
}
break;
}
synchronized(list) {
for (Object object: list) {
Socket socket = (Socket)object;
if (socket==s) continue;
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println(ipaddress + ": " + message);
writer.flush();
}
}
}
try { reader.close(); } catch (Exception e) {}
}
catch (Exception e) {
System.err.println(e);
}
}
}
Client like this ...
// xagyg wrote this, but you can copy it
import java.util.*;
import java.io.*;
import java.net.*;
public class ChatClient {
public static void main(String[] args) throws Exception {
Socket s = new Socket(args[0], 4444);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String message;
new SocketReader(in).start();
while ((message = reader.readLine())!=null) {
out.println(message);
out.flush();
if (message.equals("quit")) break;
}
in.close();
out.close();
}
}
class SocketReader extends Thread {
BufferedReader in;
public SocketReader(BufferedReader in) {
this.in = in;
}
public void run() {
String message;
try {
while ((message = in.readLine())!=null) {
System.out.println(message);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
How do you handle multiple client to connect to one server? I have this LogServer.java
import javax.net.ssl.*;
import javax.net.*;
import java.io.*;
import java.net.*;
public class LogServer {
private static final int PORT_NUM = 5000;
public static void main(String args[]) {
ServerSocketFactory serverSocketFactory =
ServerSocketFactory.getDefault();
ServerSocket serverSocket = null;
try {
serverSocket =
serverSocketFactory.createServerSocket(PORT_NUM);
} catch (IOException ignored) {
System.err.println("Unable to create server");
System.exit(-1);
}
System.out.printf("LogServer running on port: %s%n", PORT_NUM);
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(is, "US-ASCII"));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException exception) {
// Just handle next request.
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException ignored) {
}
}
}
}
}
}
and an embedded applet with part of the code like this e.g
import java.io.*;
import java.util.logging.*;
public class LogTest
{
private static Logger logger = Logger.getAnonymousLogger();
public static void main(String argv[]) throws IOException
{
Handler handler = new SocketHandler("localhost", 5000);
logger.addHandler(handler);
logger.log(Level.SEVERE, "Hello, World");
logger.log(Level.SEVERE, "Welcome Home");
logger.log(Level.SEVERE, "Hello, World");
logger.log(Level.SEVERE, "Welcome Home");
}
}
now the question is if I run "java LogServer" on the server, it will open the application and waiting for input stream and if I open my site, it will start streaming the log. But if I open one more using other computer/network, the second site does not log the stream. seems like it's because the first one still bind to port 5000.
How do I handle this?
How does socket actually work with multiple client / one server?
For every client you need to start separate thread. Example:
public class ThreadedEchoServer {
static final int PORT = 1978;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new thread for a client
new EchoThread(socket).start();
}
}
}
and
public class EchoThread extends Thread {
protected Socket socket;
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
}
public void run() {
InputStream inp = null;
BufferedReader brinp = null;
DataOutputStream out = null;
try {
inp = socket.getInputStream();
brinp = new BufferedReader(new InputStreamReader(inp));
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
return;
}
String line;
while (true) {
try {
line = brinp.readLine();
if ((line == null) || line.equalsIgnoreCase("QUIT")) {
socket.close();
return;
} else {
out.writeBytes(line + "\n\r");
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
You can also go with more advanced solution, that uses NIO selectors, so you will not have to create thread for every client, but that's a bit more complicated.
This is the echo server handling multiple clients... Runs fine and good using Threads
// echo server
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_X_Client {
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
}
}
Also here is the code for the client.. Just execute this code for as many times as you want to create multiple client..
// A simple Client Server Protocol .. Client for Echo Server
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 NetworkClient {
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");
}
}
}
I guess the problem is that you need to start a separate thread for each connection and call serverSocket.accept() in a loop to accept more than one connection.
It is not a problem to have more than one connection on the same port.
See O'Reilly "Java Cookbook", Ian Darwin - recipe 17.4 Handling Multiple Clients.
Pay attention that accept() is not thread safe, so the call is wrapped within synchronized.
64: synchronized(servSock) {
65: clientSocket = servSock.accept();
66: }
Here is code for Multiple Client to one Server Working Fine ..
Give it a try :)
Server.java:
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
class Multi extends Thread{
private Socket s=null;
DataInputStream infromClient;
Multi() throws IOException{
}
Multi(Socket s) throws IOException{
this.s=s;
infromClient = new DataInputStream(s.getInputStream());
}
public void run(){
String SQL=new String();
try {
SQL = infromClient.readUTF();
} catch (IOException ex) {
Logger.getLogger(Multi.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Query: " + SQL);
try {
System.out.println("Socket Closing");
s.close();
} catch (IOException ex) {
Logger.getLogger(Multi.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class Server {
public static void main(String args[]) throws IOException,
InterruptedException{
while(true){
ServerSocket ss=new ServerSocket(11111);
System.out.println("Server is Awaiting");
Socket s=ss.accept();
Multi t=new Multi(s);
t.start();
Thread.sleep(2000);
ss.close();
}
}
}
Client1.java:
import java.io.DataOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
public class client1 {
public static void main(String[] arg) {
try {
Socket socketConnection = new Socket("127.0.0.1", 11111);
//QUERY PASSING
DataOutputStream outToServer = new DataOutputStream(socketConnection.getOutputStream());
String SQL="I am client 1";
outToServer.writeUTF(SQL);
} catch (Exception e) {System.out.println(e); }
}
}
Client2.java
import java.io.DataOutputStream;
import java.net.Socket;
public class client2 {
public static void main(String[] arg) {
try {
Socket socketConnection = new Socket("127.0.0.1", 11111);
//QUERY PASSING
DataOutputStream outToServer = new DataOutputStream(socketConnection.getOutputStream());
String SQL="I am Client 2";
outToServer.writeUTF(SQL);
} catch (Exception e) {System.out.println(e); }
}
}