I am trying to write a piece of software that
accept simple UDP messages (text strings) from simple UDP client,
opens connection to another server and forwards messages to it
listens for that server reply and
forwards that reply back to the client.
So it is a simple intermediate server.
To visualise the communication:
Client <---> Intermediate Server <---> "Real" Server
The client connects to the Intermediate but has no idea that the message it sends is being forwarded to another server, or that it's reply is actually from another server. As far as the client cares it the Intermediate server is the real server.
I am trying to use Java's DatagramChannel for this, but not quite sure how to correctly do this in a non-hack way. Do I use two DatagramChannels? One for Client--Intermediate and the other for Intermediate--Real Server?
An general outline of approach would be appreciated, particularly if I need to open a socket every time I need to forward a message from the Intermediate to the Real Server, or if I can keep that socket open somehow.
You only need one datagram socket for this, and you can keep it open for the life of the process.
Related
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.
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.
I have written a socket program in Java. Both server and client can sent/receive data to each other. But I found that if client sends data to server using TCP then internally TCP sends acknowledgement to the client once the data is received by the server. I want to detect or handle that acknowledgement. How can I read or write data in TCP so that I can handle TCP acknowledgement. Thanks.
This is simply not possible, even if you were programming in C directly against the native OS sockets API. One of the points of the sockets API is that it abstracts this away for you.
The sending and receiving of data at the TCP layer doesn't necessarily correlate with your Java calls to send or receive data. The data you send in one Java call may be broken into several pieces which may be buffered, sent and received independently, or even received out of order.
See here for more discussion about this.
Any data sent over a TCP socket is acknowledged in both directions. Data sent from client to server is the same as data sent from server to client as far as TCP wire communications and application signaling. As #Eric mentions, there is no way to get at that signaling.
It may be that you are talking about timing out while waiting for the response from the server. That you'd like to detect if a response is taking too long. Is it possible that the client's message is larger than the server's response so the buffering is getting in the way of the response but not the initial request? Have you tried to use non-blocking sockets?
You might want to take a look at the NIO code if you have not already done so. It has a number of classes that give you more fine grained control over socket communications.
This is not possible in pure Java since Java's network API all handles socket, which hides all the TCP details.
You need a protocol that can handle IP-layer data so you can get TCP headers. DLPI is the most popular API to do this,
http://www.opengroup.org/onlinepubs/9638599/chap1.htm
Unfortunately, there is not Java implementation of such network. You have to use native code through JNI to do this.
I want to detect or handle that acknowledgement.
There is no API for receiving or detecting the ACKs at any level above the protocol stack.
Rethink your requirement. Knowing that the data has got to the server isn't any use to an application. What you want to know is that the peer application has received it, in which case you have to get the peer application to acknowledge at the application protocol level.
I have something like a proxy server (written in java) running between my clients and the actual video server (made in c++). Everything the clients send goes through this proxy and is then redirected to the server.
It is working fine, but I have some issues and think it would be better if I could make this proxy server only to listen to the clients requests and then somehow tell the server that a request has been made from the client side, and that it is supposed to create a connection with the client directly.
Basically in the TCP level what I want to happen is something like this:
1- whenever a client sends a SYN to my proxy, the proxy just sends a message to the real server telling the ip and port of the client.
2- The server would then send the corresponding SYN-ACK to the specified client creating a direct connection between client and server.
The proxy would then be just relaying the initial requests (but not the later data transfer) to the actual server. I just don't know if that is possible.
Thank you very much
Nelson R. Perez
That's very much the way some games (and Fog Creek CoPilot) do it, but it requires support on both the server and the client. Basically the proxy has to say to the client and server "try communicating with the directly on this ip and this port" and if they can't get through (because one or both is behind a NAT or firewall), they fall back to going through the proxy.
I found this good description of "peer to peer tcp hole punching" at http://www.brynosaurus.com/pub/net/p2pnat/
Does the proxy and server lives on the same machine? If so, you can pass the connection to the server using Socket Transfer or File Descriptor Passing. You can find examples in C here,
http://www.wsinnovations.com/softeng/articles/uds.html
If they are on the different machines, there is no way to pass connection to the server. However, it's possible to proxy the IP packets to server using VIP (Virtual IP). This is below socket so you have to use Link layer interface, like DLPI.
You don't have control of TCP handshake in userland like that. This is what firewalls/routers do but it all happens in the kernel. Take a look at the firewalling software for your platform - you might not even have to code anything.