I want to write a server which listens on the given port for connections and puts sockets into BlockingLinkedQueue from which the consumer thread will read messages. I accept incoming connections in this way:
ServerSocket serverSocket = new ServerSocket(port);
while (true)
{
Socket socket = null;
socket = serverSocket.accept();
queue.put(socket);
}
When I try to connect in parallel from two separate hosts it occurs that responses to the first one are sent to the second one after establishing the second connection. When I change my code to this listed below the second connection is merely refused:
while (true)
{
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
queue.put(socket);
}
My questions are:
What's the difference between this two situations? Why in the first situation messages are sent to the second host?
How should I refactor my code in order to create separate connections between my server and both hosts and handle them in parallel?
What's the difference between this two situations?
In the first case, you are using the same port for multiple connections. In the second case, you are discarding the server port so any waiting connections for be refused.
Why in the first situation messages are sent to the second host?
Due to a bug in code, not shown here.
How should I refactor my code in order to create separate connections between my server and both hosts and handle them in parallel?
Create a thread for each connection.
Related
I'm in the process of writing a messaging program, and I'm running into a spot where I'm having trouble understanding how to pass a socket over to a new thread for handling outbound messages via TCP. I'm currently using UDP packets for messages coming from a client, to the server, which, being UDP, doesn't require very much processing, as it's simply listening for incoming packets, before it de-serializes the objects, and processes them as needed in a separate thread. My problem now is, I'm setting up a client initiated TCP socket for reverse traffic, from the server to the assorted clients that connect. I've done a bit of research, and I already understood that each client should have their own thread for handling outgoing messages, along with another thread simply for accepting the incoming connections. I'm unsure of how to actually achieve this, and I've done some research into the topic.
I've found this: http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
The resource above basically verified my original suspicion that this would have to be handled by threads dedicated to the client. They included psuedo code here, which is representing my listener thread.
while (true) {
accept a connection;
create a thread to deal with the client;
}
I'm a bit of a visual learner, and I have been searching for some type of an example where this is done. I'm unsure of what variable I'd be passing over to the thread that keeps the original connection open, and pushes data back to clients. I'm also having a little bit of trouble grasping whether it even keeps the same socket open, or if a new one needs to be established, which then, makes me believe a firewall could interfere, but I know that won't be the case.
Can somebody explain this for me in detail? If possible, an example would be greatly appreciated!
I'll be likely replying and commenting on responses in about 15-30 minutes from the time this is posted.
What you are doing sounds correct. I typically implement a server like this (simplified version with no tracking of the clients and so on):
#Override
public void run() {
//start listening on the port
try {
serverSocket = new ServerSocket(port);
logger.info("Listening for connections on port " + port);
} catch (IOException e) {
logger.error("Cannot start SocketListener on port " + port + ". Stopping.", e);
return;
}
while (!stopped) {
try {
//wait for connection
Socket newSocket = serverSocket.accept();
ClientThread client = new ClientThread(newSocket);
Thread clientThread = new Thread(client, MEANINGFUL_THREAD_ID);
clientThread.start();
} catch ...
}
}
where serverSocket is a ServerSocket instance variable and stopped is a flag I use to stop the listener thread.
So to answer your questions in the comment, you normally pass the Socket object to each client thread so that that thread can work with the input and output stream and handle closing of the socket and so on. Once you "accept" a socket connection, you do not need to recreate the ServerSocket, you simply call .accept() again to start waiting for a new connection.
In most cases, you will need to keep track of all client threads in your server so that you can stop the server gracefully or do broadcasts for example.
I'm trying to write a simple Java chat application in Server/Client.
I'm confusing in below method at server.accept() :
private void waitForConnection() throws IOException {
showMessage("Waiting for someone to connect... \n");
// `connection` is an instance of `java.net.Socket`
// `server` is an instance of `java.net.ServerSocket`
connection = server.accept();
showMessage("Now connected to " + connection.getInetAddress().getHostName());
}
Please tell me connection is equal to what?
And also server.accept() returns what?
Any helps would be awesome.
Assuming your server variable is a java.net.ServerSocket then the accept() method returns a java.net.Socket object.
From the returned Socket object, you have access to both the InputStream and OutputStream to read from and write to the connected client.
Your program should halt until a client connects. That's what the line connection = server.accept(); does. Returning type is a type of Socket, too.
That's the "connection" to your client, you can read from and write to.
Check this and that site to read more about network programming in Java.
when you do connections between two systems then you require a socket.
Socket of one system is connected with socket of another system. Both these sockets are connected via I/O stream. you can write to this stream and can read from this stream.
One system serves as server and another system serves as client .
As socket is combination of port no. and IP so server open its port no. and client try to connect with the server's IP and port no.
For connection to be maid the server accepts the incoming socket using accept() function. accept() function returns a local socket which is connected to another socket at the client..
accept() waits until a client socket arrives.
I have a producer sending data for 15 seconds. I just replicate the same program and run it from different window while the first producer is already running. I get "Port 3333 already in use, java.net.BindException: Address already in use"
How can I make multiple producers (multi-process not threaded) send data at the same socket? However I dont know from where the port 3333 comes into picture.
What might be wrong with my program? I can provide the complete problem statement if desired. However in short I am using custom Kafka Producer to send data and I want two such Kafka Producers to send data.
I guess the program that you are starting is trying to listen for connections on a fixed port 3333, and when you start second instance it gives error of "Already Bound". See if there is a way to change that port using some arguments. But I cannot comment on that as you have not provided any source.
But I am just going to explain how things work in normal scenarios
Suppose consumer is listening on port 3333, then it will become the server and accept the connections on that port. And multiple clients can send data on that port to server
Sample Client Program
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 3333); //3333 is the port on which the server is listening
DataOutputStream outToConsumer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromConsumer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); //Only if consumer sends something in reply
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
modifiedSentence = inFromConsumer.readLine();
So multiple producers will be clients and send data to consumers who are listening on dedicated ports. Keep in mind multiple consumers will not be able to listen on same socket,
you will have to use different ports for different consumers.
If you have a connection-oriented protocol (e.g. TCP) the server usually only listens for connections on the advertised port. When a client connects, the server's accept call results in a connection on effectively a random other port number, allowing the main server thread/process to continue listening for new connections on the advertised port.
With a datagram-based protocol (e.g UDP) this isn't an issue because no client maintains a persistent connection.
Either solution could work for you--which one to prefer depends on the nature of the traffic.
I have two wifi modules M1 and M2 that connect to my access point. I have an android phone that connects to the same access point. I have a socket server on my android phone and the two modules join to the server as clients. Now my question is, is it possible to send a string message from my phone to module M1 without having to send anything to M2. I want to choose between clients to send the message to. Is it even possible in Java?
Ok, here goes.
//setting up server
ServerSocket serverSocket = new ServerSocket(8000, 0, IPaddress);
//creating a client socket to accept it
Socket clientSocket = serverSocket.accept();
Now, I accept the client in a seperate thread so that the main thread does not freeze becauz accept() function is blocking.
I don't know how to create a new thread every time a new client connects. Also I dont know how to limit the number of clients that can connect. I need at most 5 clients and no more.
Yes, it is possible. You need to maintain a separate connection to each client. The ServerSocket class has an accept() function which returns a Socket object. That object represents a connection between two points, your server and one client. You can call ServerSocket.accept() multiple times in a loop to accept all incoming connections. Each Socket object returned will be for a different client.
In order to have the server send a message to a specific client, it will need to know which socket belongs to which client, so the clients will have to send some message to the server identifying themselves, and the server will need to read and interpret that message. Then it can respond with the appropriate response for that specific client.
Post your code if you are still having trouble.
UPDATE because you added code to the question: See the Android Documentation about creating threads. That will be a lot of reading beyond this post on stackoverflow.
As to accepting connections and starting threads, just do it in a loop:
for(int i = 0; i<5; i++){
clientSocket = serverSocket.accept();
// start a new thread, passing it the clientSocket as an argument
}
Other possibly useful links:
https://developer.android.com/resources/articles/painless-threading.html
https://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
What would this statement do:
ServerSocket ss=new ServerSocket(4646);
Please explain in layman terms.
The statement effectively tells the JVM to listen on port specified (4646) for incoming connections. By itself it doesn't mean anything since you will have to take incoming connections to that port and use them to build normal Socket objects that will be then used for ingoing/outgoing data.
You could say that the ServerSocket is the object through which real TCP sockets between clients and the server are created. When you create it, the JVM hooks to the operating system telling it to dispatch connections that arrive on that port to your program.
What you typically do is something like:
public AcceptThread extends Thread {
public void run() {
ServerSocket ss = new ServerSocket(4646);
while (true) {
Socket newConnection = ss.accept();
ClientThread thread = new ClientThread(newConnection);
thread.start();
}
}
}
So that you will accept incoming connections and open a thread for them.
Straight from the ServerSocket Java docs:
Creates a server socket, bound to the specified port.
What's a server socket?
This class implements server sockets. A server socket waits for requests to come in over the network. It performs some operation based on that request, and then possibly returns a result to the requester.
public ServerSocket(int port) throws IOException
documentation:
Creates a server socket, bound to the
specified port. A port of 0 creates a
socket on any free port.
That would bind your ServerSocket to port 4646 on the local machine.
You could then accept sockets on this connection with
// pick up server side of the socket
Socket s = ss.accept();
Now, your client can connect to your server, establishing a socket connection, like this
// pick up client side of the socket, this is in a different program (probably)
Socket connectionToServer = new Socket("myserver",4646);