The challenge: We have a number of clients in distributed outposts that I have to manage with a central server. As some clients are located in DMZ or behind proxies, they should be connecting to the server!
As I only have to deal with one client at a time, the server doesn't necessarily have to be able to handle multiple clients simultaniously, however, I would like to see a list of the clients that are trying to connect to the server. Plus, I would like to see more information about the clients than just the IP address, for example the geographic location and some information, if the client has some files in a specific directory that the central server is interested in. My question is, how I best do smth like that.
Sure, I could simply show every client trying to connect in a listbox and accept only the one that I want to connect with, but is that really the way to go? I doubt I can get more information about the client than it's IP address?
I was wondering, if this calls for UDP. The clients send UDP datagrams that just inform the server that they are alive and that they want to connect. On the server, I see all these clients listed with the data they sent. I can then select one client, send an answer/"connection request" with UDP so that this particular client will connect via TCP to the server?
Is that possible?
This sounds like using a hammer to crack a nut. Just have them all connect via TCP. Then you get their presence, their IP address, anything else they care to send you. Deal with them all at once. It's not hard.
Related
I'm trying to build instant messaging app. Clients will not only send messages but also often send audios. And I've decided to use websocket connection to communicate with clients. It is fast and allows to send binary data.
The main idea is to receive from client1 message and notify about it client2. But here's the thing. My app will be running on GAE. And what if client1's socket is opened on server1 and client2's is opened on server2. This servers don't know about each others clients.
I have one idea how to solve it, but I am sure it is shitty way. I am going to use some sort of communication between servers(for example JMS or open another websocket connection between servers, doesn't matter right now).
But it surely will lead to a disaster. I can't even imagine how often those servers will speak to each other. For each message server1 should notify server2, server2 should notify client2. But things become even worse when serverN comes into play.
Another way I see this to work is Firebase. But it restricts message size to 4KB. So I can't send audios via it. As a solution I can notify client about new audio and he goes to my server for it.
Hope I clearly explained the problem. Does anyone know how to solve it? Or maybe there are another ways to build such apps?
If you are building a messaging cluster and expect communicating clients to connect to different instances of the server then server-server communication is inevitable. Usually it's not a problem though.
First, if you don't use any load balancing your clients will connect to the same server 50% of time on average (in case of 2 servers).
Second, intra-datacenter links are fast and free in all known public clouds.
Third, you can often do something smart on the frontend to make sure two likely to communicate clients connect to the same server. For instance direct all clients from the same country to the same server using DNS load balancing.
The second part of the question is about passing large media files. It's a common best practice to send it out of band - store on the server and only pass the reference to it. Like someone suggested in the comment, save the audio on the server and just send a message like "audio is available, fetch it from here ...". You don't need to poll the server for that. Just fetch it once when the receiving client requests it.
In general, it seems like you are trying to reinvent the wheel. Just use something off the shelf.
Let all client get connected to multiple servers and each server keeps this metadata
A centralized system like zookeeper stores active servers details
When a client c1 sends a message to client c2:
the message is received by a server (say s1, we can add a load balancer to distribute incoming requests)
s1 will broadcast this information to all other servers to get which server the client c2 is connected to OR a better approach to use consistent hashing which decides which server the client can connect to & in this approach message broadcast is not required
the corresponding server responses to server s1 (say s2)
now s1 sends the message m to s2 and server s2 to client c2
Cons of the above approach:
Each server will have a connection with the n-1 servers, creating a mesh topology
Centralized system (zookeeper) becomes a single point of failures (which is solvable)
Apps like Whatsapp, G-Talk uses XMPP and TCP/IP.
I am presently working on a client-server solution to transfer files to another machine via a socket network connection. I am fairly new to the whole client-server thing and therefore have the following - admittedly very basic - question:
For the file transfer, does it make any difference if I am sending the file from a client to a server or from a server to a client?
Any qualified insight into this will be much appreciated!
For the file transfer, does it make any difference if I am sending the file from a client to a server or from a server to a client?
Basically, no it does not matter. Once you have the connection made you are free to send data in both directions. Although you have to consider that a server won't accept data that is sent to it unless it explicitly reads from the socket.
To be a bit more general, server and client are completely arbitrary for a home brewed implementation of data transfer. If you boil this down to the simplest concept then you are just opening a socket and writing data to it on one side, and on the other side you are reading from a different socket.
You might choose to implement a single client program capable of connecting other clients (P2P) and sending files back and forth. In that case you could call the "server" the program that is currently sending the file, and the "client" is the program currently receiving.
Alternatively, you could implement two programs, one for client and one for server. Your server will listen for connections and the client will decide when it wants to connect to the server.
Remember that there are network limitations for connecting. If the program that is listening for connections is behind a firewall then you have to be sure you are forwarding the correct ports. If you are connecting machines within a LAN then you probably have nothing to worry about.
I have a client and a server application that is communicating just fine, there is a TIdCmdTCPServer in the server and a TIdTCPClient in the client.
The client has to authenticate in the server, the client asks the server for the newest version information and downloads any updates, and other communications. All this communication with TIdTCPClient.SendCmd() and TIdTCPClient.LastCmdResult.Text.Text.
The way it is, the server receives commands and replies, the clients only receives replies, never commands, and I would like to implement a way to make the client receives commands. But as I heard, if the client uses SendCmd it should never be listening for data like ReadLn() as it would interfere with the reply expected in SendCmd.
I thought of making a command to check for commands, for example, the client would send a command like "IsThereCommandForMe" and the server would have a pool of commands to each client and when the client asks, the server send it in the reply, but I think it would not be a good approach as there would be a big delay between the commands being available and the client asking for it. I also thought of making a new connection with new components, for example a TIdCmdTcpClient, but then there would be 2 connections for each client, I don't like that idea as I think it could easily give problems in the communication.
The reason I want this, is that I want to implement a chat functionality in the client, and it should be receiving messages from the server without asking for it all the time, imagine all clients continually asking the server if there is message for them. And I would like to be able to inform the client when there is an update available instead the client being asking if there is any. And with this I could send more commands to the client too.
what are your thoughts about this ? how can I make the server receiving commands from the clients, but also sends them ?
TCP sockets are bidirectional by design. Once the connection between 'client' and 'server' has been established, they are symmetric and data can be sent at any time from any side over the same socket.
It only depends on the protocol (which is just written 'contract' for the communication) which communication model is used. HTTP for example uses a request/reply model. With Telnet for example, both sides can initate data transmissions. (If you take a look at the Indy implementation for Telnet, you will see that it uses a background thread to listen for server data, but it uses the same socket connection in the main thread to send data from client to server).
A "full duplex" protocol which supports both request/response and server push, and also is firewall-friendly, is WebSockets. With WebSockets (a HTTP upgrade), the server can send data to the connected client(s) any time. This would meet your 'chat' requirement.
If you use TIdTCPClient / TIdCmdTCPServer, corporate firewalls might block the communication.
I'm in the process of trying to write a chat application and I have a few issues
that I trying to work out. The application is basically a chat application that works on a Lan. One client acts as the
host and other clients can connect to the host and publicly chat among themselves. I want also the option of a client starting
a private chat with an already connected client. So what is the best way for this to happen. For example should the request message (which
contains the ip address of client) route through the host and then if the requested client wants to connect , then they initiate the connection
using ip of the requesting client. Should this also be on a separate port number. Does it matter if your application uses a number of ports.
Or, when ever a client connects to a host, the host should send them a list of users with there ip addresses, and then the client can
attempt a connection with the other client for a private chat.
Hope this all makes sense. Any help would be appreciated
Thanks
If you are just interested in a quick-and-dirty chat facility that only needs to work over a LAN, I'd suggest having all clients send and receive broadcast UDP packets on a single well-known port number. Then no server is necessary at all, and thus no discovery is necessary either, and things are a lot simpler.
If you really want to go the client-server route, though, you should have your server (aka host) machine accept TCP connections on a single well-known port, and then have it use select() or poll() to multiplex the incoming TCP connections and forward any data that comes in from each incoming TCP socket to all of the others sockets. Clients can connect via TCP to the server at this well-known port, but the clients will have to have some way of knowing what IP address to connect to... either from having the user type in the IP address of the server, or by some discovery mechanism (broadcast UDP packets could be used to implement that). This way is a lot more work though.
I'm all for creating my own but depending on time constraints sometimes I look for alternatives like this I used it in a company I worked at before. It's really good. But if you decide to make your own you first have to map out a logic, structure, Database and so on before you even think about code..
I am building an app that uses a async socket connection with a web server.
For sending large amounts of data I would like to connect two iPhones into a Peer to Peer connection using an async socket. I am more familiar with GCDAsyncSocket than to the iOS SDK socket API.
I have done something similar, but only within a local network were I would user NSNetService to publish a presence and get the addresses needed from the p2p connection.
Can you give me a hint on how to connect two iPhone over the internet using a p2p socket connection?
I do not know much about NSNetService but it seems that it only works in a local network. If you want to establish a p2p connection from an iphone to another you will always have the problem of several NATs (Network address translators) in your route. How to find the address and route to the peer? And how to get trough all the firewalls and NATs?
I am working on an app that needs to deal with the same problem and I have answered a similar question before which I will cite here:
Actually, it IS possible. You may want to google for something called
"UDP hole punching" or "TCP hole punching".
The main approach in short: Assuming you got something like a relay
server, that is some server in the internet that is publicly
addressable from every private LAN that is connected to the www. No
you have your two clients A and B in (different) private LANs, with
some Network address translation (NAT) going on, that want to
establish a peer to peer connection.
First of all both will tell the server their IP address and the port
they have in their own LAN. In the UDP or TCP packet, the server will
find the public address and port of the device (or the NAT (router)).
So the server knows the private and the public IP address as well as
the ports.
If now A wants to communicate with B, it asks the server for help. The
server will send a message to B that A wants to communicate with her
telling her A's public and private IP and port. A gets back B's public
and private information and port.
Now here is where the magic happens. Both clients now send packets out
to establish a connection simultaneously to the private and public
addresses of the other party and thus punching a whole in their NATs
such that incoming connections will not be blocked. Even if one
party's connection establishing packets will arrive before this whole
is created, the other's packets will get through to such that a
connection can be created.
Beware of some NATs that scan the data for IP addresses and translate
them as well, but if you encrypt your data or change the appearance of
the address (complement, ...) you will be fine.
Now the master question, how can the server communicate with one of
the clients without an active connection. Well in this case you can
use "connection reversal" and apple's "push notifications". Use the
"push notifications" (pn) to tell a client behind a NAT that there is
something of interest going on and that it should contact the server.
Once it has done that the connection is active and can be used in the
previous described fashion.
I hope this helps some people that get to this problem although the
post is quite old!
Now if you find this solution helpful and you try to implement it, please tell me if you are successful in getting the public ip and port of the server-client connection on the server side. You can also answer my question about this on stackoverflow.
Please be specific, u may use GCDAsyncSocket to connect 2 phones, u may use sample code from Github.