I want to implement a Server which listens endless on a specific port to receive data from many clients (never in parallel, only serial). The first thing I tried is to run the server and then launch a few clients in serial (one after the other).
This sounded very easy to implement, but I actually got into the problem, that the code works only when I run it in debug mode with at least one breakpoint in the server code (but the same fault as when running it normally without a breakpoint), very strange to me.
However here is the server code:
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
#Override
public void run() {
try {
int counter = 0;
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
System.out.println("Waiting for client...");
Socket socket = serverSocket.accept();
System.out.println("Accepted");
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectStream = new ObjectInputStream(inputStream);
while(inputStream.available() > 0 ) {
String to = (String)objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
objectStream.close();
inputStream.close();
System.out.println("Closing socket");
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
And here the client code:
public class TaskSenderClient {
public static void main(String args[]){
try{
Socket s = new Socket("localhost",2003);
OutputStream os = s.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject("test");
oos.close();
os.close();
s.close();
}catch(Exception e){
System.out.println("Client exception");
e.printStackTrace();
}
}
}
this is the console output when running in debug mode with breakpoint in the server code row System.out.println("Accepted");:
Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
test
2
Closing socket
Waiting for client...
Accepted
test
3
Closing socket
Waiting for client...
And the output when running in normal mode / without breakpoints in debug-mode:
Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
I don't get any exception... Can someone help? It's my first attempt to re-use a socket connection in java.
EDIT: Checking inputStream.available returns different values
I just added a System.out.println(inputStream.available()); before the while in server code. This prints
always 7 in debug-mode with breakpoint
7 (in first run) and 0 (in all other attemps) afterwards in non-debug mode / without breakpoints
EDIT 2: First wait until inputStream.available != 0
This solution also works for me. However, I removed this code snippet here, because checking of available() seems not to be the correct way for that! -> see the solution!
EDIT 3: New server code, which uses NonEmptyInputStream which checks per PushbackInputStream for non-empty streams:
As this uses the EOFException it seems not to be an optimal solution to me, so I also removed this code snippet (instead see solution below). The usage of exceptions in "correct" code is discussed in the comments below...
InputStream.available() can return 0 if there is no data yet, meaning the client didn't send some yet or at least it is not arrived yet. If you add a breakpoint the client has more time to send the data.
You can either add logic like your client first sends how many objects it writes, the server reads the amount and then reads that many objects before it stops reading.
Another possibility would be to insert a PushbackInputStream between the ObjectInputStream and the InputStream and then do a read() on the PushbackInputStream, check the result for -1 which means end-of-stream and if it was not -1, use unread() to push the read byte back into the stream before using the ObjectInputStream methods.
Here you have an example of your originally posted class rewritten with the last pattern:
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
#Override
public void run() {
try {
int counter = 0;
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
System.out.println("Waiting for client...");
Socket socket = serverSocket.accept();
System.out.println("Accepted");
InputStream inputStream = socket.getInputStream();
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
ObjectInputStream objectStream = new ObjectInputStream(pushbackInputStream);
for(int i; (i = pushbackInputStream.read()) != -1;) {
pushbackInputStream.unread(i);
String to = (String) objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
objectStream.close();
pushbackInputStream.close();
inputStream.close();
System.out.println("Closing socket");
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
or here again with try-with-resources which is preferable over manually closing AutoClosables.
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
int counter = 0;
while(true) {
System.out.println("Waiting for client...");
try (Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
ObjectInputStream objectStream = new ObjectInputStream(pushbackInputStream)) {
System.out.println("Accepted");
for(int i; (i = pushbackInputStream.read()) != -1;) {
pushbackInputStream.unread(i);
String to = (String) objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
System.out.println("Closing socket");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
available() is not a valid test for end of stream. See the Javadoc. You should read from the object stream until EOFException is caught.
Related
I have a server and a client set up in this way. I can't find the cause of the EOFException, because it happens randomly. It throws the following exception every time a client connects, but I can't figure out the source of it. It always occurs before it reads what the client has sent. The exception always is at this line:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Here is the exception:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End$3.run(End.java:62)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
Here is my server code:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
Here is my client code:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
What I've Tried
I've tried to fix this issue many times before. I tried to create object output streams. I've switched the order that I initialize the object input stream and object output stream. This is so that the server doesn't get frozen in a deadlock with the client. I have no idea what could be causing this error.
I think I know what is going on here, but I can't be certain because your code is fragmentary, and the symptoms are not well characterized. (The exceptions are unlikely to really be random, for example.)
First there is one indisputable fact. A one side of a connection sees an EOFException because the other side has closed the network connection. That's what that exception means.
In your case, the server gets the exception in the ObjectInputStream constructor because the constructor attempts to read an object stream header that the client side never sends ... on that connection.
Now, the theory. I think I know why. Here is the relevant part of your code (with some bits snipped out for brevity).
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
Notice that there are two sockets! The first one is created and passed to the shutdown hook. The second one is created and used within send and then closed.
I think the problem is the first Socket. When that is created, it establishes a connection to the server. The server code will accept it and then attempt to read. The read will block ... since the client side hasn't written anything to that socket. The client will then call send which opens and uses a different Socket.
Eventually, the client application exits.
When it exits, the shutdown hook closes the first socket. That causes the server side to see the end of stream ... and triggers the EOFException.
So how to fix this?
It rather depends on the "big picture". Is the real client sending a single message to the server, or does it need to reuse the socket to send multiple messages?
Assuming the former, the solution is simple:
Get rid of the code that creates a socket and passes it to a shutdown hook. As you have written it, it serves no useful purpose.
Rewrite the send method to use try with resources; e.g.
public void send(Object object) throws IOException {
try (Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(object);
}
}
Note that the above will automatically close the 3 resources in the correct order.
I'm sending a file and its name through Socket to a ServerSocket.
It works "partially" -- the server gets the file and saves it to disk but
it does not exit the loop in the copy() method in the ClientSession class.
public class Client{
DataOutputStream dos =null;
DataInputStream dis=null;
File f =new File("c:/users/supernatural.mp4");
public static void main(String[]ar) throws Exception{
try {
System.out.println("File upload started");
Socket socc = new Socket("localhost",8117);
dos = new DataOutputStream(socc.getOutputStream());
//send file name
dos.writeUTF(f.getName());
//send the file
write(f,dos);
//Files.copy(f.toPath(),dos);
//this prints
System.out.println("Data has been sent...waiting for server to respond ");
dis = new DataInputStream(socc.getInputStream());
//this never reads; stuck here
String RESPONSE = dis.readUTF();
//this never prints prints
System.out.println("Server sent: "+RESPONSE);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
//close the exceptions
clean();
}
}
private static void write(File f,DataOutputStream d) throws Exception{
int count;
DataInputStream din = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
byte array[] = new byte[1024*4];
while((count =din.read(array)) >0){
d.write(array,0,count);
}
d.flush();
//this prints
System.out.println(" done sending...");
din.close();
}
}
//Server
public class MySocket implements Runnable{
int worker_thread=2;
volatile boolean shouldRun =false;
ServerSocket server;
String port = "8117";
//ExecutorService services;
static ExecutorService services;
public MySocket() {
this.server = new ServerSocket(Integer.valueOf(port));
services = Executors.newFixedThreadPool(this.worker_thread);
}
//A METHOD TO RUN SERVER THREAD
#Override
public void run(){
while(this.shouldRun){
Socket client =null;
try{
client = server.accept();
}catch(Exception ex){
ex.printStackTrace();
}
//hand it over to be processed
this.services.execute(new ClientSessions(client));
}
}
public static void main(String[]ar) throws Exception{
Thread t = new Thread(new MySocket());
t.start();
}
}
//the ClientSession
public class ClientSessions implements Runnable{
Socket s;
public ClientSessions(Socket s){
this.s = s;
}
DataInputStream dis=null;
DataOutputStream dos=null;
boolean success =true;
#Override
public void run(){
//get the data
try{
//get inside channels
dis = new DataInputStream(this.s.getInputStream());
//get outside channels
dos = new DataOutputStream(this.s.getOutputStream());
//read the name
//this works
String name=dis.readUTF();
String PATH_TO_SAVE ="c://folder//"+name;
//now copy file to disk
File f = new File(PATH_TO_SAVE);
copy(f,dis);
//Files.copy(dis,f.toPath());
//this doesnt print, stuck in the copy(f,dis) method
System.out.println("I am done");
success =true;
}catch(Exception ex){
ex.printStackTrace();
}finally{
//clean resources...
clean();
}
}
//copy from the stream to the disk
private void copy(File f,DataInputStream d)throws Exception{
f.getParentFile().mkdirs();
f.createNewFile();
int count =-1;
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
byte array[] = new byte[1024*8];
count =d.read(array);
while(count >0){
out.write(array,0,count);
count =d.read(array);
System.out.println("byte out: "+count);
}
//this never prints
System.out.println("last read: "+count);
out.flush();
out.close();
if(success)dos.writeUTF("Succesful");
else dos.writeUTF("error");
}
}
//for the clean method i simply have
void clean(){
if(dis!=null)dis.close();
if(dos!=null)dos.close();
}
I commented this //Files.copy(dis,f.toPath()); from server
because it does not go to next line after writing file to disk, sometimes even stuck there.
Could some pls point me in the right path, I believe i am doing something very wrong here
dont know if this is helpful but the client runs in eclipse and server in netbeans
Think about your procotol:
The Client sends the file name, then sends the binary file, then waits for the server response.
The Server reads the file name, then the binary file until the stream is closed, then sends the success message.
But the stream is never closed since the client is waiting for the response, hence you have a deadlock in your protocol.
This is usually solved by sending the file size first and having the server read exactly that many bytes.
Alternatively you can use the TCP's one-way shutdown feature to send a signal to the server that the output stream of the socket is closed. That can be done with socc.shutdownOutput();
And please use try-with-resources to avoid resource leaks (you must close the Socket, too).
Fixed Client:
try {
System.out.println("File upload started");
try (Socket socc = new Socket("localhost", 8117);
DataOutputStream dos = new DataOutputStream(socc.getOutputStream());
DataInputStream dis = new DataInputStream(socc.getInputStream())) {
// send file name
dos.writeUTF(f.getName());
// send the file
Files.copy(f.toPath(), dos);
dos.flush();
System.out.println("Data has been sent...waiting for server to respond ");
// signal to server that sending is finished
socc.shutdownOutput();
String RESPONSE = dis.readUTF();
// this never prints prints
System.out.println("Server sent: " + RESPONSE);
}
} catch (Exception ex) {
ex.printStackTrace();
}
Server:
public class MySocket implements Runnable {
int worker_thread = 2;
volatile boolean shouldRun = true;
ServerSocket server;
int port = 8117;
ExecutorService services;
public MySocket() throws IOException {
this.server = new ServerSocket(port);
services = Executors.newFixedThreadPool(this.worker_thread);
}
// A METHOD TO RUN SERVER THREAD
#Override
public void run() {
while (this.shouldRun) {
Socket client = null;
try {
client = server.accept();
} catch (Exception ex) {
ex.printStackTrace();
}
// hand it over to be processed
this.services.execute(new ClientSessions(client));
}
}
public static void main(String[] ar) throws Exception {
new MySocket().run();
}
}
class ClientSessions implements Runnable {
Socket s;
public ClientSessions(Socket s) {
this.s = s;
}
#Override
public void run() {
// get the data
try (DataInputStream dis = new DataInputStream(this.s.getInputStream());
DataOutputStream dos = new DataOutputStream(this.s.getOutputStream())) {
// read the name
// this works
String name = dis.readUTF();
String PATH_TO_SAVE = name;
// now copy file to disk
File f = new File("c://folder", PATH_TO_SAVE);
Files.copy(dis, f.toPath());
dos.writeUTF("Succesful");
System.out.println("I am done");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The issue with your code is, that you read from an input stream of a socket, that is never closed.
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
byte array[] = new byte[1024*8];
count =d.read(array);
while(count >0){
out.write(array,0,count);
count =d.read(array);
System.out.println("byte out: "+count);
}
//this never prints
System.out.println("last read: "+count);
d.read(array) is actively trying to read from the socket, blocking until it receives something. Since the InputStream is actively blocking, it never returns a value less than or equal to 0. This is because the stream awaits the next package from the other end of the Socket.
Closing the Socket after sending the File should help you. In that case, the end of the Stream is reached and the InputStream returns.
Note: The InputStream you are reading from will (if the socket is closed) return a -1, as you can see within the JavaDoc.
In your case, this however might not be viable!
You want to answer the Client with "okay", or "error". If you close the socket, you cannot answer through the same Socket. The solution to this can be complex.
This situation is a bit tricky. Most frameworks out there have a Thread that reads from the SocketInputStream and passes the return value to some sort of handler (in blocking IO). Your while loop basically is this main reading loop inside the Thread. This loop will only exit, if the connection is lost and therefor the System.out.println("last read: "+count); could be changed to System.out.println("disconnected");
To keep it simple: You could give an estimation on how big the file will be and (just for testing purposes) write something like this:
DataOutputStream out = new DataOutputStream(new
BufferedOutputStream(new FileOutputStream(f)));
byte array[] = new byte[/* Big enough */ 1024 * 1024 * 8];
d.read(array); // Read the file content
out.write(array); // Write to the file
//this never prints
System.out.println("last read: "+count);
I have left out every error check here! This means that you only read one package from the server, which has to be the File.
I have created a server-client project where the server keeps listening and prints the information. However, when i shutdown the client, the server remains open. The problem is that I need to insert this into another application, and, if the server does not close at first, the application will not open unless i kill the process in that port (but this is not an option to me). What should I do to properly close the server once the client disconnects?
Here is the code:
Server:
public class Server {
public static void main(String[] args) {
Connection conn = new Connection();
new Thread(conn).start();
}
private static class Connection implements Runnable {
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(5005)) {
Socket socket = serverSocket.accept();
listener(socket);
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void listener(Socket socket) throws IOException {
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
boolean alive = true;
while (alive) {
try {
outputStream.writeUTF(new Scanner(System.in).nextLine());
System.out.println(inputStream.readUTF());
} catch (IOException ex) {
ex.printStackTrace();
alive = false;
}
}
}
}
}
Client:
public class Client {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 5005)) {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
while (socket.isConnected()) {
System.out.println("Incoming data: " + inputStream.readUTF());
outputStream.writeUTF(new Scanner(System.in).nextLine());
outputStream.flush();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Since now, thank you very much!
The thing that force the system wait and not close is this line at your Server.java :
outputStream.writeUTF(new Scanner(System.in).nextLine());
Once it starts waiting the user input, it waits forever along the life time of the instance although your client is disconnected.
So what you can do ? You can create another thread that makes periodic "ENTER" inputs (if you insist using new Scanner(System.in)) for example input per 5 seconds. After the enter, or any other meaningful input, if you decide this is not from your client, don't write it to the client and wait user input again (if your client still connected !). If your client is not connected, just finish your loop.
Please check Java Robot class and this example
I'm implement a http server with version1.1 using java socket programming. I use a version 1.0 sample code and I want add the persistent connection feature by not closing socket utilt a "Connection : close" send to the server. However, I came accross with "java.net.SocketTimeoutException: Read timed out" info after an input like"localhost:8080/xxxx" on my browser and not receiving anything when tested with a client program. Code is too long, and I mention the matter parts bellow! Can you find the problems for me, thanks!!!
////////here is the server part using thread pool techs
//Webserver class
protected static Properties props = new Properties();
/* Where worker threads stand idle */
static Vector threads = new Vector();
public static void main(String[] a) throws Exception {
int port = 8080;
if (a.length > 0) {
port = Integer.parseInt(a[0]);
}
loadProps();
printProps();
/* start worker threads */
for (int i = 0; i < workers; ++i) {
Worker w = new Worker();
(new Thread(w, "worker #"+i)).start();
threads.addElement(w);
}
ServerSocket ss = new ServerSocket(port);
while (true) {
Socket s = ss.accept();
Worker w = null;
synchronized (threads) {
if (threads.isEmpty()) {
Worker ws = new Worker();
ws.setSocket(s);
(new Thread(ws, "additional worker")).start();
} else {
w = (Worker) threads.elementAt(0);
threads.removeElementAt(0);
w.setSocket(s);
}
}
}
}
//Worker class inherit from Webserver class
byte[] buf;
Worker() {
buf = new byte[BUF_SIZE];
s = null;
}
synchronized void setSocket(Socket s) {
this.s = s;
notify();
}
public synchronized void run() {
while(true) {
if (s == null) {
/* nothing to do */
try {
wait();
} catch (InterruptedException e) {
/* should not happen */
continue;
}
}
try {
handleClient();
} catch (Exception e) {
e.printStackTrace();
}
/* go back in wait queue if there's fewer
* than numHandler connections.
*/
if(!headAttri.getPersistConnec())
s = null;
//
Vector pool = WebServer.threads;
synchronized (pool) {
if (pool.size() >= WebServer.workers) {
/* too many threads, exit this one */
try{
if(s != null)
s.close();
}catch (IOException e) {
e.printStackTrace();
}
return;
} else {
if(!headAttri.getPersistConnec())
pool.addElement(this);
}
}
}
}
//in handle client I mention the socket handles here(s is the socket)
void handleClient() throws IOException {
//...
s.setSoTimeout(WebServer.timeout);
s.setTcpNoDelay(true);
//...
try{
//...handle request and response the client
//...
}finally{
//close socket if head info "Connection: close" is found
if(headAttri.getPersistConnec()){
s.setKeepAlive(true);
}
else{
s.close();
}
}
}
//////////end server part
//////here is the client part
public SimpleSocketClient()
{
String testServerName = "localhost";
int port = 8080;
try
{
// open a socket
Socket socket = openSocket(testServerName, port);
// write-to, and read-from the socket.
// in this case just write a simple command to a web server.
String result = writeToAndReadFromSocket(socket, request_str[1]);
// print out the result we got back from the server
System.out.println(result);
// close the socket, and we're done
socket.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private Socket openSocket(String server, int port) throws Exception
{
Socket socket;
// create a socket with a timeout
try
{
InetAddress inteAddress = InetAddress.getByName(server);
SocketAddress socketAddress = new InetSocketAddress(inteAddress, port);
// create a socket
socket = new Socket();
// this method will block no more than timeout ms.
int timeoutInMs = 10*1000; // 10 seconds
socket.connect(socketAddress, timeoutInMs);
return socket;
}
catch (SocketTimeoutException ste)
{
System.err.println("Timed out waiting for the socket.");
ste.printStackTrace();
throw ste;
}
}
private String writeToAndReadFromSocket(Socket socket, String writeTo) throws Exception
{
try
{
// write text to the socket
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write(writeTo);
bufferedWriter.flush();
//test
//bufferedWriter.write("GET src/WebServer.java HTTP/1.1\r\nHost: localhost\r\nConnection: close");
//bufferedWriter.flush();
// read text from the socket
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder sb = new StringBuilder();
//string handling code
String str;
while ((str = bufferedReader.readLine()) != null)
{
sb.append(str + "\n");
}
// close the reader, and return the results as a String
bufferedReader.close();
return sb.toString();
}
catch (IOException e)
{
e.printStackTrace();
throw e;
}
}
////end client part
//close socket if head info "Connection: close" is found
if(headAttri.getPersistConnec()){
s.setKeepAlive(true);
It is hard to tell from your code what you are really doing but based on this code fragment it looks like you are mixing up HTTP keep alive (i.e. Connection: keep-alive handling, multiple requests in a single TCP connection) with TCP keep alive (detect broken TCP connection). See Relation between HTTP Keep Alive duration and TCP timeout duration and HTTP Keep Alive and TCP keep alive for explanations about the difference.
I want add the persistent connection feature by not closing socket utilt a "Connection : close" send to the server
That's not how you do it. You have to close the connection yourself, either
after a request with a Connection: close header is received and you've sent the response, or
when you get a read timeout on the socket reading the next request.
The length of the read timeout is entirely up to you, because it is up to you to protect yourself from DOS attacks among other things.
NB calling Socket.setKeepAlive(true) has absolutely nothing whatsoever to do with it.
NB 2 You should look into java.util.concurrent.Executor rather than implement your own thread pool.
I have a chat program. Now the code works for communicate between client and server via command line. But it gives an exception (java.net.SocketException: Socket is closed) while running. Please help me to fix that problem.
In a java chat program,how will the communication be implemented between client and server?
ie.
client<-->server (between server and client)
or
client A<-->server<-->client B (server act as a bridge between two clients)
Is the 2 way communication can be implemented through a single socket?
Are there any other methods ?
How to communicate more than one client simultaneously?
server code
class Server
{
ServerSocket server;
Socket client;
public Server()
{
try
{
server = new ServerSocket(2000);
System.out.println("\tServer Started..........");
while (true)
{
client = server.accept();
Send objsend = new Send(client);
Recive objrecive = new Recive(client);
//client.close();
}
}
catch (Exception e)
{
System.out.println("Exception4 " + e);
}
}
public static void main(String arg[])
{
new Server();
}
}
class Recive implements Runnable
{
Socket client;
public Recive(Socket client1)
{
client=client1;
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
ObjectInputStream ois;
Message M=new Message();
try
{
ois = new ObjectInputStream(client.getInputStream());
M = (Message)ois.readObject();
M.display();
ois.close();
}
catch (Exception e)
{
System.out.println("Exception1 " + e);
}
}
}
class Send implements Runnable
{
Socket client;
public Send(Socket client1)
{
client=client1;
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
try
{
System.out.println("Me(server)");
M.strmessage=br.readLine();
ObjectOutputStream oos=new ObjectOutputStream(cli ent.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
catch (Exception e)
{
System.out.println("Exception " + e);
}
}
}
client code
class Client
{
public static void main(String arg[])
{
try
{
Send objsend=new Send();
Recive objrecive=new Recive();
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Send implements Runnable
{
public Send()
{
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
try
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
while(true)
{
System.out.println("Me(client)");
M.strmessage=br.readLine();
Socket client=new Socket("localhost",2000);
ObjectOutputStream oos=new ObjectOutputStream(client.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Recive implements Runnable
{
public Recive()
{
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
try
{
while(true)
{
Socket client=new Socket("localhost",2000);
ObjectInputStream ois=new ObjectInputStream(client.getInputStream());
Message CNE=(Message)ois.readObject();
CNE.display();
ois.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
First of all, don't close the streams in every run().
Secondly, check whether port for server which you are using is free.
This program makes your pc both host and server.
import java.io.IOException;
import java.net.*;
public class ClientServer {
static byte[] buffer = new byte[100];
private static void runClient() throws IOException {
byte buffer[] = new byte[100];
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds=new DatagramSocket();
int pos = 0;
while (pos<buffer.length) {
int c = System.in.read();
buffer[pos++]=(byte)c;
if ((char)c =='\n')
break;
}
System.out.println("Sending " + pos + " bytes");
ds.send(new DatagramPacket(buffer, pos, address, 3000));
}
private static void runServer() throws IOException {
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds = new DatagramSocket(3000, address);
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);
String s=new String(dp.getData(),0,dp.getLength());
System.out.print(s);
}
public static void main(String args[]) throws IOException {
if (args.length == 1) {
runClient();
} else {
runServer();
}
}
}
also follow this link
There could be multiple places where the exception could be thrown. Without a stack trace it is difficult to state so accurately, as to the cause of failure.
But the root cause, is essentially due to the fact that you are closing the InputStream of the socket in your Receiver threads after reading a message, and closing the OutputStream of the socket in your Sender threads after sending a message. Closing either of these streams will automatically close the socket, so you if attempt to perform any further operation on it, a SocketException will be thrown.
If you need to ensure that your server and client do not shutdown in such an abrupt manner, you'll have to keep reading the InputStream (until you get a special message to shutdown, for instance). At the same time, you'll also have to keep writing to the OutputStream. Two-way communication is definitely possible, and the posted code is capable of the same (if the socket remains open).
If you have to handle multiple clients, you'll need multiple reader and writer threads on the server, each listening on an instance of a Socket returned from ServerSocket.accept(); in simpler words, you need a reader-writer pair listening on a distinct socket on the server for each client. At the moment, multiple clients can connect to the Server, as each incoming connection is provided its own client Socket object on the Server, that is provided to individual reader and writer threads. The main Server thread can continue to receive incoming connections and delegate the actual work to the reader-writer pairs.
chat programms normaly have a server through which all communication goes. The reason is that other wise every client needs to know how to reach every other client. And that doesn't work in the general case.
So you'll have a server, every client registers and talks with the server, which will forward messages to other clients.
Mostly communication is done via HTTP cause this is likely to go through firewalls and proxies. You probably want to read up on long polling if you are planning for anything serious.