I'm trying to develop a Java chat server. I don't know if the better solution is to do either of:
Create a socket for each client and keep it open
Set an interval in the client application and query a database to check if there are messages for the client.
Which is the best way to go for this situation?
i suggest you to learn Serialization if you want to develop an application with UI support. Moreover, you have to create a socket for each client especially in Server side. And a Server should have threads which maybe you can call client handler, to deal with clients' requests. Query a database for checking received messages is meaningless but you can save all messages in a database maybe. My advice is if you are going to use a database (well i suggest that), use it for dealing with registration process of clients. So whenever a client sends a request to server for logging in, a thread will check will check if that client has already have an account or not in database.If not you can implement a simple register form. And logically every client will have a friend list which you should keep them in a database.
EDIT: The Server will look like this.
public class Server {
public static void main(String[] args) {
try {
ServerSocket s = new ServerSocket(8087);
System.out.println("Server Started");
while (true) {
Socket incoming = s.accept();
System.out.println(incoming.getInetAddress().getHostAddress() + " was connected!");
new ClientHandler2(incoming).start();
}
} catch (Exception e) {}
}
}
So the main point is Server should never stop to listen the specified port.
Client Handler which is a thread created in Server side.
public class ClientHandler extends Thread {
private Socket incoming;
public ClientHandler(Socket incoming){
this.incoming = incoming;
}
#Override
public void run(){}
Server will send the initialized socket into the ClientHandler's constructor and call start() method to run it.
Actually you do not have to keep connection for eternity for each client ! All you have to do is store client's state server side and then communicate via any connection. Then you can get back resource and use them more wisely when your client doesn't seem to be active for a while.
Related
How can a Server open a TCP connection through a Client which was connected to server before? Let say we have simple server like the code shows below; server waits for client connections and a handler thread serves connected clients. Client as below, every time wants to do an operation with the server, reestablish the connection, communicate with server and then close the connection. So, if server would like to open a TCP connection through the client(when there is no an active connection from client to server), how it can be done?
Server Code
public class DServer {
public static void main(String[] args) {
ServerSocket serverSocket = new ServerSocket(7800);
while(true) {
Socket socket = serverSocket.accept();
System.out.println("Server established a new connection");
HandleConnection handler = new HandleConnection(socket);
handler.start();
}
}
}
Client Code
public class DClient{
public static void main(String[] args) {
Socket socket = new Socket("localhost", 7800);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
//for every operation you do, first reestablish the connection,
//communicate with server, then close the connection.
}
}
I think you have some fundamental misunderstandings about what a client is and what a server is in a networking sense.
The server is the application listening for connections. The client is the application creating connections to the server. If you want both of your applications to be able to initiate communication at will, then your applications will need to be both clients and servers.
So your "DClient" application will need to have a ServerSocket. You "DClient" application can then inform your "DServer" application of it's host and port for when "DServer" wants to create a connection (note that things like NATing can make this sort of thing problematic if both applications are not in the same network).
Alternately, depending on your use case, you could just leave the connection from client to server open. This is the more usual approach to letting the server push data.
There is solution to create proxy server which is manage the both request client and server which called middleware for both client request.
In network programming it must required to fist server start and then client request because client server architecture.
I am trying to build a socket that is capable of having multiple TCP connections, at different ports with multiple clients simultaneously.
The situation is my socket has to receive commands from a server and redirect the commands to wireless sensors (one command to one sensor, not broadcasting), and be able to collect the corresponding data from the sensors and then send them back to the server. Connections with the server would be using TCP, but connections with the sensors could be TCP or UDP.
My main concern are the TCP connections. I am looking into java multithreaded or thread pooled socket tutorials. But the examples I’ve seen were only using a single port to handle all the connections. I’m also trying to look into other possible solutions: utilizing tomcat server, java servlet/JSP, socket channel etc…
I’m not an expert in networking or socket programming so I really hope someone with experience could point me in the right direction. Thank you for any help you can provide in this situation.
Not sure if I fully understand but it seems like it is unnecessary for me to obtain multiple ports for my situation. Seems like I would need to focus on multi threaded sockets and Java NIO topics?
And again thank you for the advice and help.
This is rather a big project to be answered in full here. But here are some general guides:
1) If you want to create a socket on one port you need to create one thread to run it. That is called a server socket. Therefore, from the main thread u need to call one thread for every socket on every port.
2) Each server socket keeps listening on a certain port and waits for clients to connect.
when a client actually connects, the server socket should open another thread for that connection alone and return back to listening.
while(myServerSocket.accept())
{
Open connection thread
}
My advice would be to learn online about how to open threads from classes and then follow the guide above.
Unless you are going over 10k connections then most web servers would be able to handle the traffic.
But maybe you should get more details on the difference between a connection, a socket, and a port. Take a look at this: What is the difference between a port and a socket?
On your question: one port can handle many connections. You don't need different ports for different connections.
My understanding of this request is that you would need to deploy several instances of your server socket application listening on their respective ports and capable of servicing multiple client connections.
By way of mathematical induction, if you have written your server app properly it should work anywhere it is deployed. Below is sample of what your server socket application run should look like
public void run()
{
try
{
while(true)
{
try
{
Thread client_thread= new Thread(new ClientReqProcessor(serverSocket.accept()));
client_thread.start();
}
catch(Exception ex)
{
logger.error("connection error: "+ex.getMessage());
}
}
}
}
Why do you want to use multiple ports? You can have multiple connections on one listening port. The connection itself runs always on different ports.
while (running)
{
try
{
#SuppressWarnings("resource")
Socket socket = serverSocket.accept();
new ServerHandler(socket); // ServerHandler is your class to handle one connection.
}
catch (IOException e)
{
...
}
}
When you really need different ports, you can create a lot of Threads, each with a ServerSocket. Ports are one of the most limited resources on your computer. The running Threads are much cheaper.
for(int i = 1000; i < 1100; i++)
{
final int port = i;
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
new ServerHandler(socket); // ServerHandler is your class to handle one connection.
}
catch(IOException e)
{
...
}
}
}).start();
}
I would like to have this setup:
Server hosting TCP socket server
Multiple clients connected over TCP (keeping connection open)
Then I would like to initiate a message from the Server to the client. I can't figure out how to do this, and have multiple client sessions at the same time. Techniques I've read involve the Server listening on a port, and when it receives communicate from a client, it launches a new thread to handle and process that, and then it goes back to listening on the port for the next request of another client.
So, then how would I tap into that and send a message to a client running on one of those threads?
My actual usage scenario if you are interested is below. Final goal is like a remote control for your file system to upload files to the server.
- Each client has a java background application running in the system tray that connects to the server
- Server hosts connections, and also hosts a RESTFul webservice to initiate communication
- Mobile device connects to Server over RESTFul webservices to request informatino about the client's filesystem. So it can drill down and find a file, then click and have the file uploaded to the server.
The idea here is mobile users needing to upload files from their desktop to the server while away from their office on a mobile device. (and this is for custom product, so can't use a third-party app_
PS: I've been looking at the simple Client-Server chat program here: http://way2java.com/networking/chat-program-two-way-communication/
You want to have a server listening at all times on a specified port. Once the server notices an incoming connection on that port you should create a new Thread to handle the communication between that client and the server, while the main thread keeps on listening for other incoming connections. This way you can have multiple clients connected to one server. Like so:
private void listen() throws IOException {
serverSocket = new ServerSocket(port)
while (GlobalFlags.listening) {
new ServerThread(serverSocket.accept();
if (GlobalFlags.exit) {
serverSocket.close();
break;
}
}
}
Where the GlobalFlags are variables to control the listening process and are not really necessary. You could do a while True and just keep listening for ever and ever.
In my project I have a main server controller which had listeners running in Threads. The controller controlled the GlobalFlags. I'm sure instead of using global flags there is a better way to do inter thread communication but for me this was the simplest at the time.
The ServerThread should be looping all the time switching between sending output to the client and receiving input from the client. Like so:
ServerThread(Socket socket) {
super("GameServerThread");
this.socket = socket;
try {
this.socket.setTcpNoDelay(true);
} catch (SocketException e) {
// Error handling
}
this.terminate = false;
}
#Override
public void run() {
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String inputLine, outputLine;
while ((inputLine = in.readLine()) != null) {
outputLine = processInput(inputLine);
out.println(outputLine);
if (terminate) {
break;
}
}
}
out.close();
in.close();
socket.close();
} catch (Exception e) {
// Error handling, should not use Exception but handle all exceptions by themselves.
}
On the client side you have a thread running through a similar loop, receiving input from the server and then sending output to the server.
In this example processInput is the function used to process the client's input. If you want the server to initiate contact you can make the server send something to the outputstream before listening for input and make the client listen first.
I have extracted this example from one of my own projects and the this.socket.setTcpNoDelay(true) is supposed to make the process faster. Reference here: http://www.rgagnon.com/javadetails/java-0294.html
"java.net.Socket.setTcpNoDelay() is used to enable/disable TCP_NODELAY which disable/enable Nagle's algorithm.
Nagle's algorithm try to conserve bandwidth by minimizing the number of segments that are sent. When applications wish to decrease network latency and increase performance, they can disable Nagle's algorithm (that is enable TCP_NODELAY). Data will be sent earlier, at the cost of an increase in bandwidth consumption. The Nagle's algorithm is described in RFC 896.
You get the current "TCP_NODELAY" setting with java.net.Socket.getTcpNoDelay()"
So to send a message to a specific client you could put all the threads upon creation in an ArrayList so you can keep track of all the currently connected clients. You can have the processInput method halt and polling a queue/variable until another class puts the message to be send in the queue/variable. So how to gain a handle on the class depends on your implementation of processInput. You could give every thread an ID (which is what I did in my project) and maybe have the processInput method poll an ArrayList at index=ID. Then to send output to the client you would have to set the variable at index=ID.
This method seems kind of clunky to me personally but I'm not really sure how else I would do it. You would probably use Queues and have processInput write the input to its Queue and then wait for another class to read it and put its response in the Queue. But I have personally never worked with Queues in java so you should read up on that yourself.
In my knowledge
1) Server hosting TCP socket server -- Possible
2) Multiple clients connected over TCP -- Possible
3) Then I would like to initiate a message from the Server to the client -- Not Possible. The Client has to initiate a connection creation, then the server might be able to send data packets to You. Example: You need to open Facebook website on your browser, Facebook server cannot decide to send its page to your PC on its own because your PC will not have a static IP address, and also if Facebook hypothetically writes code to initiate connection to Your PC, then it is as good as Your PC is the server and Facebook website/server acts as client.
I have three entities: A,B and C. A is a server and B and C are clients.
A is a multithread server implemented using the class in java.net
I would realize a communication in which B sends a message to A, A send a message to C and C send a message B.my question is: the clients C must be even a server or is must be only a client that forward the message?
public class ServerA{
public static void main(String[] args){
boolean listening = true;
int port_number = 8888;
try{
ServerSocket ss = new ServerSocket(port_number);
System.out.println("Waiting for incoming connection...");
while(listening){
new Thread(new ServerThread(ss.accept())).start();
}
}
catch(IOException ioe){ioe.printStackTrace();}
}
}
public class ServerThread implements Runnable{
#Override
public void run(){
}
}
Is there any particular reason why you would like design your architecture like that?
To answer your question: lets think a bit about it. What do you need to send a message from client C to client B? How would you want to implement it? You mentioned a channel in your comment - but what do you exactly need to open a "channel" between two clients? You need to know somehow its (client B's) location and a port client B is listening for messages on (worst case scenario each client knows about all/some other clients, better way would be to query the main server for a list of other clients/have some kind of a registry with all clients). Also, obviously, client B needs to have a port opened and be waiting for messages.
So basically client C queries server A for something, gets a response and then sends (through a socket) a message to client B, which has to be listening (just like client A was) for it. This is basically what server-client does.
If you know that it will be in a LAN or something similar then you can consider using UDP instead of TCP, but then you need to manage way more things by yourself since it is not as reliable.
This architecture reminds me more of a peer-to-peer network (where all "clients" are more like a client+server combination) with a single server which can fetch data from somewhere/do some computation.
this is not my homework(my homework is just about doing chat with a client and server which it works correctly especially with your help[:-)]
but I want to make two clients chat with each other,I don't know that when i get text from the first one how can I send that text to the other client.would you please help me.thanks.
public class MainServer {
static Socket client = null;
static ServerSocket server = null;
public static void main(String[] args) {
System.out.println("Server is starting...");
System.out.println("Server is listening...");
try {
server = new ServerSocket(5050);
} catch (IOException ex) {
System.out.println("Could not listen on port 5050");
System.exit(-1);
}
try {
boolean done = false;
while (!done) {
client = server.accept();
System.out.println("Client Connected...");
BufferedReader streamIn = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter streamOut = new PrintWriter(client.getOutputStream(),true);
String line = streamIn.readLine();
if (line.equalsIgnoreCase("bye")) {
streamIn.close();
client.close();
server.close();
done = true;
} else {
System.out.println(line);
streamOut.println(line);
}
}
} catch (IOException e) {
System.out.println("IO Error in streams " + e);
}
}}
That's it, your two "clients" will both act as client and server :
Listening to incoming things on a socket and sending things over an other sockets.
On the server, you can keep a Set of all the clients that are currently connected to the server. The server should listen for messages (can do this with a ServerSocket, and clients connect with normal Sockets). Each time the server receives a message, it sends this message back to all clients in the Set, and the clients display the message.
EDIT: this is for a client-server system, where clients connect to a central server instead of directly to each other. If you want to do direct client-to-client, one of them will just have to act as the server, and you'll need to implement a chat UI in both.
Here is a very simple, ~100 line, GUI chat program.
Have a look at Building an Internet chat system.
This explains how to write simple Clients and a Server with Java.
Unless you want to get into really complicated P2P discovery protocols, you would have to have a server to act at least as an intermediary.
In order to establish a direct client to client connection, the clients would need to know each others IP addresses. To do this, each client would first connect and "register" itself with a central server.
When a client wants to talk to another client, it would ask for that client's address from the server, then establish a connection directly with that client. So each client is acting both as a client (establishing connections with the server and other clients) and as a server (accepting connections from other clients).
It seems simple in theory, but in practice it gets more complicated. For example, what if the client you want to connect to is behind a firewall? You could have a hole in the firewall for incoming connections to get through, or you could fall back to having the communication go through the server, or if one of the clients is behind a firewall and the other isn't, the server could mediate the connection in the opposite direction.
Basically, there are two approaches:
One Chat server that receives all messages and distributes/forwards them to the clients (xmpp/jabber works this way)
One server that connects clients directly. Like on peer-to-peer networks
Looking back at your previous work, I think, the first approach is more feasible.
The server will offer one port where new clients can connect. After a client requests to participate/use the server, there server spawns a worker thread with a server socket on a different (available) port number and tell the client that port number. This is the reserved communication channel for that client with the server.
The rest is pretty straightforward: a client can send a new chat message, the server will pick it up and send it to all connected clients.
If a client disconnects, the worker thread will close the socket, return it to the pool and terminate.