Everyone is aware of socket programming in java. we write a code as below:
ServerSocket serverSocket = new ServerSocket(1234);
Socket server = serverSocket.accept();
We know that we create object of serverSocket and next we write serverSocket.accept(); code to receive client request. we know that serverSocket.accept(); wait until new request comes.
but my question is : what serverSocket.accept(); method does internally? might be is running in while loop ? how server identify that any new request is came to serve ? what is the internal implmentation of serverSocket.accept(); method? Any One has idea about this?
On Linux, the ServerSocket.accept() ultimately (in native code) does an accept syscall (see man 2 accept) which blocks waiting for a suitable incoming connection.
There is no while loop in the Java code or in the native code. I've no idea what happens inside the Linux kernel, but at that point this is no longer a Java question.
The same would probably apply for Java on Windows, and for C# or any other programming language that you cared to consider.
You can find this by your own.
public Socket accept() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isBound())
throw new SocketException("Socket is not bound yet");
Socket s = new Socket((SocketImpl) null);
implAccept(s);
return s;
}
How accept() works?
Related
I'm new at network programming and i have been searching for a solution to my problem here but couldn't find one. What I want is to have a server that can receive files from multiple sockets at the same time. When a server accepts new connection socket it wraps that socket with a ClientThread class. Here is the code:
public class Server extends Thread {
private ServerSocket server;
private Vector<ClientThread> clients;
#Override
public void run() {
listen();
}
private void listen() {
new Thread("Listening Thread") {
#Override
public void run() {
while (true) {
try {
Socket socket = server.accept();
ClientThread newClient = new ClientThread(socket);
newClient.start();
clients.addElement(newClient);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}.start();
}
ClientThread is a private class inside the Server class. It's always listening for an Object from ObjectInputStream, but also I want to be able to receive one big file after the object. And that is why I think i should use multithreading. Here is the code:
private class ClientThread extends Thread {
public Socket socket;
private boolean loggedIn;
private ObjectInputStream ois;
private BufferedInputStream bis;
public ClientThread(Socket socket) {
this.socket = socket;
loggedIn = true;
InputStream is = socket.getInputStream();
ois = new ObjectInputStream(is);
bis = new BufferedInputStream(is);
}
#Override
public void run() {
receive();
}
private void receive() {
while (loggedIn) {
try {
// this method blocks i guess
Object object = ois.readObject();
// after the object comes the large file
byte[] bytes = new byte[SOME_SIZE];
int bytesRead;
int totalRead = 0;
// reading the large file into memory
while ((bytesRead = bis.read(bytes, totalRead, bytes.length - totalRead)) > -1) {
totalRead += bytesRead;
}
// rest of the code for handling received bytes.......
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
}
}
}
I'm not sure if receiving data like this is even possible since all these client sockets are sending data to the same port on this server (i guess?). And if clients are sending data at the same time, Server needs to know which data is for which client. Is this already taken care of, or i need entirely different approach here?
I don't know if this is a stupid question, but like I said I'm just starting learning this stuff. Also i couldn't test my program because i don't even have code for the Client yet. Just want to make sure I don't go wrong at the very start. If this is wrong, feel free to post some ideas. :) Thanks!
For a start it's not bad :)
You can improve later on by using a Selector but that's another topic.
Some clarifications though: the ServerSocket listens on a specific port. When a remote client connects to it, a communication channel (i.e. socket) is created. If another client connects, another socket is created. Both sockets are different channels and won't interfere with each other because they are connected to a different remote IP and port.
It all has to do with how TCP headers and IP headers are formed: a TCP data packet is sent with its header containing the source and destination port, on top of IP header containing the source and destination IP. Those are used to discriminate between the different sockets.
Regarding the "broadcast" you want to do (as per your comment in #Rajesh's answer), you have options:
Do it yourself in pure TCP with ServerSocket and Socket like you started
Switch to UDP and use MulticastSocket, which has the advantage of issueing a single send, but you'll have to deal with missing/unordered datagrams in your client code (UDP does not guarantee delivery or ordering, like TCP does)
Check NIO with Selector and SocketChannel
Investigate frameworks like jGroups or Netty which do the I/O stuff for you
As you're learning, I suggest you do that in the above order. Using a framework is nice, but going through coding yourself will teach you a lot more.
This will work functionally. Each thread is reading from a separate socket connected to different client (address + port). They are separate streams, so no issues in reading from that like this.
However it would be much better to use asynchronous sockets.
Few things that can be taken care in the current implementation:
1) As a good practice, close the streams/sockets when transfer is complete.
2) For every new connection, a new thread is created. That will not scale. Even some one can send many requests and bring down your app. Would be better to use a thread pool. "ClientThread" can just implement "Runnable" and when a new connection is received, just submit the new "ClientThread" to thread pool. (In this case, would be better to name it as ClientTask instead of ClientThread)
As mentioned, it would be much more efficient and scalable to use asynchronous socket, but it will take some time master it. With this, you can use just one thread to read all sockets in parallel and depending on load, can use the same thread or a pool of threads to process the data received from all the sockets. Note that, even if use a pool, you will not need separate thread for processing each socket...Just to make best use of multiple CPU Cores, can use multiple threads to process the data.
You may try either java nio (Selector + SocketChannels) or netty library. Netty is much easier to use compared to nio.
OK. I feel dumb. I cannot find what I'm looking for.
I am opening 50 ServerSockets and adding them to a List of ServerSockets:
ServerSocket ss = new ServerSocket(getPortNumber());
SOCKETS.add(ss);
I get that I need a new thread for each connection:
new Thread() {
public void run() {
ServerSocket ss = new ServerSocket(getPortNumber());
while(true) {
Socket client = ss.accept();
//handle client
}
}.start();
So, my question is, "Do I have to use a while loop until I get a connection?"
I mean, is there a way to listen for an attempt to connect before using the ss.accept to assign Socket client?
Do I have to use a while loop until I get a connection?
It depends. If you're only expecting one connection you don't need a while loop: otherwise, you do.
I mean, is there a way to listen for an attempt to connect before using the ss.accept to assign Socket client?
The question doesn't make sense. That's what accept() does.
NB creating the ServerSocket already puts the port into listening state that can be connected to. But it is accept() that accepts connections, and nothing else.
The fact that you're creating 50 listening ports already indicates a severe design problem. You only need one. Don't waste system resources.
This all sounds like an XY problem.
We decided that (in our case) it is best to have a dedicated server socket for each client. Therefore, I am following the answer to this SO question:
Server Listening on Multiple Ports [Java]
I'm working on a game with a event based structure with the main game logic hosted on a server; currently it's a very small featureset that only allows to host one game between exactly two participants. I've read on various questions about ServerSocket and none of them answers my question. I already took a look at
ServerSocket accept continues to block
ServerSocket.accept()
Java ServerSocket won't accept new connections until close() is called on the accepted socket
ServerSocket accept() method
In my project I utilize ObjectInputStream and ObjectOutputStream. Everything works as expected (receiving / sending both on server and client side), but after both sockets are registered, the accept method of the ServerSocket instance continues to block forever, even if the same code is invoked before. Perhaps it's an issue that appears after communicating over a socket once?
My server log shows the following:
waiting for accept
accepting first socket
sending an event to socket1 for informing about waiting for the opponent
waiting for accept
accept second socket
sending responses to both sockets
waiting for accept (and blocking forever)
When the log says response events where sent, they were properly received and processed at the client side. The client side debug outputs show that the next event is definitely sent. Maybe it's about not closing the client sockets (mentioned in the third linked question)? Anyway I can't close the client sockets because further communication would be impossible.
Client side code
public void send(Event e) {
try {
ObjectOutputStream out = new ObjectOutputStream(
socket.getOutputStream());
out.writeObject(e);
out.flush();
log.debug("sending event... "+e);
}
catch(IOException ioe) {
log.fatal("constructing oos failed", ioe);
}
}
Server side code
#Override
public void run() {
running = true;
while(running) {
try {
Socket s = socket.accept();
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Event event = (Event) ois.readObject();
try {
Event[] response = controller.consume(event);
ObjectOutputStream oos = new ObjectOutputStream(sockets[0].getOutputStream());
oos.writeObject(response[0]);
oos.flush();
ObjectOutputStream oos2 = new ObjectOutputStream(sockets[1].getOutputStream());
oos2.writeObject(response[1]);
oos2.flush();
}
catch(...) {
// multiple catch clauses for different exceptions
// all just logging (nothing passes silently!)
}
}
}
For shortening, the method for assigning the two sockets to the Socket[] array was left out, but since there are no exceptions, keeping the socket works. Do you have any idea what could cause the described behavior? Thank you in advance.
The accept method only accepts new connections. Since you only have two clients attempting to connect to your server, it will hang indefinitely on your third invocation of accept.
Side note: You don't need to continuously create new ObjectInputStreams and ObjectOutputStreams. You can just create one of each for each Socket and keep references to them for reuse.
I'm doing some network programming in Java. in a loop I open a socket , send some data and close it. but I get the exception of "connection already in use" . I guess that happens since I use a same port at each repetition of the loop. how long does it take for the OS (Ubuntu 11.10) to close the socket and free the port? thanks
the simplified code look like this
while(true){
Socket clientSocket = new Socket("localhost", 5000);
PrintWriter outToServer = new PrintWriter( clientSocket.getOutputStream(),true);
outToServer.println ("Hi") ;
clientSocket.close();
}
It can take quite a while (e.g. up to 3 minutes if there is unsent data)
In your case you are using a different local port (same remote port doesn't matter) each time so it shouldn't matter.
BTW: Creating a new connection is pretty expensive, I would try to re-use a connection rather than opening a new one each time. In the example above it could be as much as 1000x faster. ;)
I'm accepting a connection from a client and then passing that connected socket off to another object, however, that socket needs to be non-blocking. I'm trying to use getChannel().configureBlocking(false) but that does not seem to be working. It needs to be non-blocking because this the method below is called every 100ms. Is there some other way that I should be making this non-blocking? Thanks for any help!
public void checkForClients() {
DataOutputStream out;
DataInputStream in;
Socket connection;
InetAddress tempIP;
String IP;
try {
connection = serverSocket.accept();
connection.getChannel().configureBlocking(false);
System.err.println("after connection made");
in = new DataInputStream(connection.getInputStream());
out = new DataOutputStream(connection.getOutputStream());
tempIP = connection.getInetAddress();
IP = tempIP.toString();
System.err.println("after ip string");
// create a new user ex nihilo
connectedUsers.add(new ConnectedUser(IP, null, connection, in, out));
System.err.println("after add user");
} catch (SocketTimeoutException e) {
System.err.println("accept timeout - continuing execution");
} catch (IOException e) {
System.err.println("socket accept failed");
}
}
Two things:
Why aren't you using a ServerSocket if you're listening for connections?
If you want to accept multiple clients you want to use a loop.
The basic structure of a multi-client server is:
while (true) {
// accept connections
// spawn thread to deal with that connection
}
If the issue is blocking on the accept() call, well that's what accept() does: it blocks waiting for a connection. If that's an issue I suggest you have a separate thread to accept connections.
See Writing the Server Side of a Socket.
I would expect your code to block on the accept call, never getting to the configureBlocking call.
I typically spin off a separate thread for each socket connection, and let it block until a connection is actually made/accepted This allows the main thread to continue unblocked while it is waiting for client connections.
If you're looking for non-blocking sokets, my suggestion is to use Selectors and ServerSocketChannels with the NIO package.
http://java.sun.com/j2se/1.4.2/docs/guide/nio/
If the typical blocking socket doesn't give you the availability you need (a connection every 100ms does seem tight). You should look at a non-blocking socket. Here is a tutorial. You can also look at Apache MINA to make this easier.
One approach is to use an I/O loop (event loop) in a single threaded environment. Take a look at Deft web server for inspiration. (Especially the start() method in IOLoop)