Ok so I've found out Sockets are not serializable... so I cant pass them over TCP...
My problem is I have a homework assignment where I have 10 servers that must listen on one socket(lets call it request). For input from any of x number of clients that write to that socket. Then after one of the server processes reads a message from request it must communicate with that client over its own socket...
I tried making each server socket and the request socket on the server side, then passing those to the clients when they connected to the server... but this doesn't work...
Any tips on how I might do this? Having TCP not be 1-1 is really toying with me here.
Passing a socket over a TCP connection is like trying to pass a telephone over a telephone call, or trying to fax your fax machine. What you need to do is organize another connection between the parties concerned.
EDIT: In fact your assignment as stated doesn't even make sense:
I have 10 servers that must listen on one socket(lets call it
request).
That's not even correct terminology. Servers listen at ports, not sockets, and 10 servers listening at one port is impossible. They must each have their own port.
For input from any of x number of clients that write to that socket.
See above. Clients don't write to 'that socket'. They create their own socket that is connected to the server port, and they write to that.
Then after one of the server processes reads a message from request it
must communicate with that client over its own socket
If the server has received a connection from a client it already has a socket representing its endpoint to that connection. So all the server has to do is write the response back to the same socket it read the request from.
In short you have a major terminology problem, but you don't have a software problem at all.
Passing sockets seems crazy to me. If you're trying to write a better server, you'll have a hard time beating Netty. I'd recommend giving it a look.
Related
I am completely new to creating a network connection in java so I apologize if this is a stupid question.
I am trying to create a D&D companion in java that will allow a player to create their character and then send it to the DM so that they can view it and make changes and send it back to the player. I want to be able to make it so that any time a field is changed on one computer it will also be changed on the other computer.
After a bunch of research online I have been able to create a socket connection between the DM(server) and the player(client) and pass a message between the two but I am not sure how a socket connection works after this initial connection is made. My research has not been very clear on this. I have found many resources that have said that java closes the socket after a message has been passed and many that say that the socket stays open.
If java closes the socket then my problem is easy enough to solve because then I will just have to open a new socket every time I need to pass data making sure that I pass the IP address of the client to the server the first time I make a connection.
My real questions come in when a socket stays open.
If the socket stays open and multiple clients connect to the server, will the server just shout over the network whenever it transmits a message so that all clients receive the message? (If this is the case then I know I can just attach a username to the front of the message so that the client can determine if the server is talking to it.)
If the server does not shout then how do I specify which client I want the server to talk to?
Will I have to add a loop to my receive methods so that the client/server is constantly listening for a transmission from the server/client or will java automatically do so after I run the method the first time?
I have found many resources that have said that java closes the socket after a message has been passed
You found them where?
and many that say that the socket stays open.
All those are correct. Java never closes connections. The application closes connections.
If java closes the socket then my problem is easy enough to solve because then I will just have to open a new socket every time I need to pass data making sure that I pass the IP address of the client to the server the first time I make a connection.
It doesn't.
My real questions come in when a socket stays open.
If the socket stays open and multiple clients connect to the server, will the server just shout over the network whenever it transmits a message so that all clients receive the message?
No. It will respond via the socket that is connected to the corresponding client.
(If this is the case then I know I can just attach a username to the front of the message so that the client can determine if the server is talking to it.)
Unnecessary.
If the server does not shout then how do I specify which client I want the server to talk to?
The server responds via the same socket it read the request from.
Will I have to add a loop to my receive methods so that the client/server is constantly listening for a transmission from the server/client
No, you will have to add a thread per accepted socket, that loops reading requests until end of stream.
or will java automatically do so after I run the method the first time?
No.
You seem to have been reading some truly appalling drivel. Take a look at the Custom Networking section of the Java Tutorial.
Adding to EJP's wise answer, it might be worth clarifying:
Sounds like you (wisely) use TCP, so your Socket represents a connection between 1 server and 1 client. No "shouting". In examples such as this , when connection is established (namely, client obtains a Socket by calling "new Socket" and server obtains a Socket by calling "accept"), those Sockets are dedicated to those 2 specific endpoints. So if 10 clients connect to 1 server, the server will keep 10 Sockets and won't mix them up. A bit like a poor secretary that has 10 phones on his desk and answers them all - despite the mess, each earpiece is clearly connected to 1 customer.
The connection can hold for a while & serve several messages. It will terminate when either one of the sides calls 'socket.close', or it can be terminated by underlying 3rd parties (operating system, proxies, firewalls).
For your first version, or for simple business requirements, it's probably enough to converse over this 1 simple connection. However, for commercial critical data that requires 'assurance of delivery', you might need to invest some careful thought & possibly tools such as RabbitMQ.
Good luck:)
Goal
I'm making a chat application for android and am currently testing with 2 phones which must eventually work for a few thousand users.
Problem
I get a ConnectionException saying "Connection refused" whenever the 2 phones try connecting to each other via sockets.
Current Design
Each phone starts a ServerSocket, calls the accept() method waiting for some Socket to connect to, and whichever phone sends a message first will create a client Socket. I'm certain the IP addresses I'm using are correct (they're actually both using the same external IP).
I believe the problem is with the ports. I generate a port number at random, and if it's free to use, I say ServerSocket s = new ServerSocket( randomPortNumber ).
What I think is the source of the problem
What I think is the problem is this port number is one sitting behind an NAT router. So when a Socket tries to connect to the ServerSocket using something like Socket socket = new Socket( ip, serverSocketRandomPortNumber ), it will try to connect to the NAT router and feed it this port number which won't work since the router itself is not listening on this port, but the phone behind the router is.
Questions and thoughts
My question is, how do I deal with this problem?
Do I have to change my design?
If I must, an alternative design I'm thinking of is using a single ServerSocket on a web host and use it to redirect messages sent from client sockets to other client sockets.
I'd be implementing the server-side in php referencing something along these lines:
http://php.net/manual/en/sockets.examples.php
And I would still use Java for the client-side.
Since one of the phones is behind a NAT router, nothing can initiate a connection to it unless port forwarding (or some other techniques) is enabled on the router.
The usual way a chat application is implemented is, there is a common server that all clients will connect to.
You don't have to write your own chat server (unless you really want to). I suggest using the XMPP protocol. A list of already made servers here. On the client side (Android), you can find libraries you can use here.
If you have a Java client Socket connected to a Java server's ServerSocket, how do you then obtain the Java server object in the client class?
I have had a look at the Socket class and there seems to be no method for getting hold of a server object through the Socket.connect()ion.
The reason I am asking, is that I would like to send an instruction from my client to the server to deregister the client from subscribing to further updates from the server. My server-client relationship is based on the Observer pattern.
To carry out the instruction, I believe I need to obtain the server object.
I am asking this question because I have not found anything on Google or stackoverflow.com which combines the Observer pattern with server-client socket relationships.
Of course that may indicate my approach is terminally flawed, but if it is, let it be a warning to others :)
Its not 100% clear what you're asking, but here goes.
If you want the remote client to indicate to the server side that it is done, then have it send a message that the server side understands to mean done, then simply close the socket object on the server side and on the client. The server socket may continue listening for more connections if appropriate.
If the socket handling the client connection on the server side is to shut down the server socket so it will no longer listen for incoming connections, then simply pass both sockets to the code that is handling the socket which is handling the client connection.
I am writing this game in Java and have problems with networking architecture.
I decided I will UDP packets. I am just at the beginning, but the problem I am facing is that it seems to be that server have to respond from exactly same IP/Port to client (which is behind router which uses NAT) as client connected that server.
For example I have client A behind router. Client A has IP (local) 192.168.8.100 and it connects server B from port 1234. Server is on 11.11.11.11:2345.
When client A connects to server B it uses 192.168.8.100:1234 but router converts that to (for example) 22.22.22.22:6789.
Now, when server wants to send packets to that client it has to be from 11.11.11.11:2345.
I would like to send data from another port like 11.11.11.11:2222, but this does not seem to work, at least not with my router.
I want to use different port because I want to have two threads one for listening and one for sending data, and each thread would have it's own DatagramSocket. But, as i said once client A connects to server on port 2345, I can not send data from port 2222.
Does anyone know how is this handled? I am doing it in Java, but it's not really a language specific problem.
UPDATE
After #Perception commented I have some more questions regarding his comments:
OK, so if I understand this correctly, if I have server which is hosting 1000 games, each with 2 players, all sending/receiving will have to be done through the same DatagramSocket.
As I understand DatagramSocket is thread safe so I guess I can have one thread doing:
datagramSocket.receive();
while at the same time second thread is doing
datagramSocket.send(.....);
Correct?
Also, two threads can send data at the same time through the same DatagramSocket? Is sending in any way serialized, meaning that second send() starts only after previous send() is finished or is data being sent at the same time?
gorann, I'm not sure if I'm understanding you correctly, but it sounds like you're trying to control the port on which the server communicates with the client. There's no way to control this, and for good reasons.
This is one of the trickier differences between TCP and UDP.
When a new TCP session is initiated, the server side call to accept() gives you a new socket and the OS handles multiplexing the various sessions for you. With UDP, you need to handle the multiplexing yourself. But you need to do so in a way that works with NATs and other firewalls.
The way NAT works is that when it sees an outgoing packet, it creates a temporary rule allow packets to return along the same port pair. Data returning from a port that the client has not yet sent to will likely be blocked.
This gives you two choices:
You could do all of your communication through a single port. This is not a bad option, it just means that you need a way to identify client sessions and route them to the appropriate thread.
You could create a separate port and instruct the client to send to that one instead. Have the server listen on a fixed port. The client sends a message to there, the server then sets up a new session port and sends that number back to the client using the server's listen port. The client then sends a message to the session port, which causes the NAT to open up that port and allow return traffic. Now the client and server thread have their own private port pair.
Option 1 is a bit more work because it requires data to be exchanged between threads, but it scales up better. Option 1 is easier and more CPU efficient because each session thread can be independent, but there are a finite number of ports available.
Either way, I recommend that you have the client include a semi-unique session id in each packet so that the server has more than just the client address and port number to verify who belongs to each session.
Essentially Im trying to get many many java clients connect to a socket on my ColdFusion server (Using the Socket Gateway). However before i even start to code this, Im a little confused about sockets and their performance. First of all, are sockets meant for many(1000+) clients connecting to one socket (say port 2202) on one server? How is the performance if all there waiting for is basically a ping, or something such that when these clients receive this "ping" they can go get some new data.
Thanks,
Faisal Abid
Socket is identified by following tuple,
Source IP
Source Port
Dest IP
Dest Port
Protocol (TCP or UDP)
Even 1000 clients all connect to the same port (dest port), each will get its own socket. So you will have 1000 sockets open.
It's going to be tough to maintain 1000 sockets with blocking I/O, which usually means 1000 threads. You need to use NIO. We have a server written with Mina, which can handle 2000 connections at peak.
First of all, are sockets meant for
many(1000+) clients connecting to one
socket (say port 2202) on one server
Yes, your server will open a socket on port 2202, and 1000 client will connect to it.
Server open server socket, and client will open client socket, it different.
How is the performance if all there
waiting for is basically a ping, or
something such that when these clients
receive this "ping" they can go get
some new data
On server, you use getInputStream function to get data from client, and getOutputStream function to send data to Client.
Notice: you should use Thread to process each request of client
There is nothing wrong with many socket clients that use blocking I/O (you may have a look at this article for more information about that). However, there are another approaches that can better fit your needs here:
nio;
multicasting;
Hi connecting with 1000 clients at the same time using simple java socket programming is not the perfect way. The probelm is that in fedora linux default maximum no of file can be open is 1024 and in windows it is 2048 or something like that. so in your server side you will find more than 1000 files open and after that if client will go on increaing then you will find too many files opnened error. so the better way is to use non blocking socket programming (I mean to say to use SocketChannel) Using socket channel at the same time as per i have check we can connect with 20,000 clients without any problem.
So better use nio. there is a very good book from Oreilly publication for java nio.
I have used java nio (socket channel)
Thanks
Sunil Kumar Sahoo