I want to write a simple program in c++ that use tcp socket to communicate with the same program on another computer in lan.
To create the tcp socket I could make the user write the ip and the port to make the connection. But I also need to be able to autodetect in the local area network if there is any computer also running the program.
My idea was:
when the program is autodetecting for available connection in lan, it will send all ips a message via udp to a specific port, meanwhile it will also keep listening to a port waiting to eventual answer.
when the program on the other computer is opened for lan connection, it will keep listening to the a port in case another computer is trying to detect, then it will send also via udp the response messagee notifying the possibility of connection.
All the security system is another problem for which I don't need answer now.
// Client 1:
// Search for all ips in local network
// create udp socket
// send check message
// thread function listening for answers
// if device found than show to menu
// continue searching process
// Client 2 (host) :
// user enable lan connection
// create udp socket
// thread function listening for detection requests
// if request structure is right send back identification message
// continue listening for request
My question - Is there a more efficient or standard way to do something like that?
Testing whether another computer is listening on a given port is what hackers do all day to try to take over the world...
When writing a software like you describe, though, you want to specify the IP and port information. A reason to search and automatically find a device would be if you are implementing a printer, for example. In that case, as suggested by Hero, you could use broadcasting. However, in that case, you use UDP (because TCP does not support that feature).
The software on one side must have a server, which in TCP parlance means a listen() call followed by an accept() until a connection materialized.
The client on the other side can then attempt a connect(). If the connect works, then the software on the other side is up and running.
If you need both to be able to attempt a connection, then both must implement the client and server (which is doable if you use ppoll() [or the old select()] you know which event is happening and can act on it, no need for threads or fork()).
On my end, I wrote the eventdispatcher library to do all those things under the hood. I also want many computers to communicate between each others, so I have a form of RPC service I call communicatord. This service is at the same time a client and a server. It listens on a port and tries to connect to other systems. If the other system has a lower IP address, it is considered a server. Otherwise, it is viewed as a client and I disconnect after sending a GOSSIP message. That way the client (larger IP address) can in turn connect to the server. This communicator service allows all my other services to communicate without having to re-implement the communication layer between computer over and over again.
Related
Writing a UDP client-server app in C++ (done that lots of times before in many languages in the past 15 years), but somehow this one is not working correctly.
I cannot post actual code nor minimal reproducible app at the moment but I am willing to pay for live help if anyone is available to help solve this quickly with screensharing.
I think this is a particularity with C++ sockets and the way I am using them in this specific app which is quite complex.
Basically the issue is that the packets sent from the server to the client are not received by the client, only when said client is on a separate nat.
When both in same local networking and using their local IP, everything works as expected.
Here is what I am doing :
Client sendto(...) packets through UDP to the server using a specific server host and port 12345 (and keeps sending these non-stop)
On another thread, client bind(...) on port 12345 and "0.0.0.0" and tries to poll() and recvfrom() in a loop (poll always returns 0 here when client is on a separate nat)
Server bind() on port 12345 and "0.0.0.0" then poll() and recvfrom() in a loop
Upon receiving the first UDP message from a client, it starts a thread for sending
UDP messages back to the client on a new socket, using the
sockaddr_in that it got from the recvfrom() to pass in the sendto() commands.
Result : Server perfectly receives ALL messages from all clients, and sends all messages back to all clients, but any client that is not on the same NAT will never receive any messages (poll() always returns 0).
As far as I understand it, when the client sends a UDP message to the server on a specific remote port (12345 in this case), it will punch a hole in its NAT so that it can receive messages back from the remote server on that port...
I tested five different client network configurations :
Local network with the server, using local IP addresses (WORKS)
Local network with the server while client is using a VPN thus going through a remote NAT (DOES NOT WORK)
Local network with the server but client is using the WAN ip address to connect to the server (DOES NOT WORK)
Client at an actual remote network from a friend's connection, behind a router (DOES NOT WORK)
Client going through a wifi hotspot created using my phone (DOES NOT WORK)
For all tests above, the server was correctly receiving all communications from clients.
I also tried forcing the port to 12345 for the sendto() instead of using the sockaddr_in as set from recvfrom(), same issue.
Am I doing anything wrong ?
If you want to help but need to see actual code, I can do that live with screen sharing and I will pay for the help.
Thanks.
Also, if anyone can point me to a great site where I can pay for VERY QUICK help, please let me know, I don't even bother searching google because I really want actual advice from people who tried these services, not ads trying to rip me off...
Only the original receiver socket is allowed to reply to the client, because it's the client request that opens the port in the NAT. So either use the same socket in the server to receive and reply, or get the port that the second server socket was bound to and transfer it with an initial message through the original server port, so that A can send to it and punch the hole.
It looks so strange to create two half duplex sockets when a socket is a full duplex communication object that I'd go with the first option.
I am trying to write a distributed server system (consisting of server 1="main", and server 2="replacement" for now). Don't mind some dirty methods, it's just to achieve a basic function a distributed server would achive.
Currently I have both servers running via SO_REUSEADDR and a TCP Socket (maybe UDP will solve my problem, but I wanna try it either way with TCP first) on the same machine.
Main server sends establishes a connection with the Replacement server and clients connecting to it.
Now what I want to achieve: The main server should send the socket of the connecting clients to the replacement server, so in case the main server can't work anymore (timeout or what ever) the replacement server can work with the clients and send/recv with them.
The socket I send from main to the replacement server is the one I get with ClientSocket = ::accept(ListenSocket, NULL, NULL); where ClientSocket is a SOCKET (UINT_PTR).
The replacement server can't send/recv to the clients even though the main server gets terminated midway.
Is that because each server, even though they run on the same port, need to be connected via a ::connect from the clients?
EDIT: If my theory is true, this should be solved by using UDP instead of TCP as well, no?
EDIT2: With distributed server I mean a server which in case of a failure will be replaced by another without the clients task getting interrupted.
EDIT3: If there is a better and more simple way to do this, I'd like to know about that as well. I'm not too fond of sockets and server communication as of now that's how I came up with my idea to solve it.
You cannot send a socket between machines. A socket is an OS concept. It represents (in this case) a connection between the server and a client. This connection cannot be resumed on a different machine that has a different IP address because a TCP connection is defined to be established between a pair of addresses and a pair of ports.
The UINT_PTR on one machine means nothing to another machine. It is an opaque value. It is an OS handle.
UDP does not solve the problem since the client needs to notice that the IP address is is communicating with has changed.
Even if you manage that you have the problem that a server failure kills all data on that server. The other server cannot resume with the exact same data. This is a basic problem of distributed computing. You cannot keep the state of all three machines completely in sync.
Make the clients tolerate interruptions by retrying. Make the servers stateless and put all data into a database.
This is a very hard problem to solve. Seek off-the-shelve solutions.
I'm writing client-server application and I need my server to find all clients in some network. I've already found some info here: Discovering clients on a wifi network, but I still don't understand how to implement this. Maybe somebody can say where I can find some code examples.
Thanks in advance.
PS. Working on c++, windows.
Generally TCP/IP is used as a communication protocol between client and server. For Windows platform Winsock library is used to implement TCP/IP. The server binds and listens on a port for incoming connections. Just like a webserver like stackoverflow listens by default on port 80 and then client (browsers) connects to it.
Here is a link to start. Here is sample
Normally all the client connects to server which listens on a well defined port. The server is only one hence the IP address and port is well know to all the client and hence they can connect to it.
In you case you want your server to have ablity to discover all the clients in the network. To achieve this the server needs to broadcast to network some message. The client will receive this message and will respond to the server that they are available on such IP and they can connect to server or provide additional information to server. Normally instead of broadcast, multicast is used which is limited broadcast. All the clients and server will subscribe to the multicast group which is a special kind of IP address. When server send a message to this multicast address all the client, which are subscribers of this address will receive this message and can respond back. Here is a sample
Edit: you can also use boost lib to implement multicast: sender eg., receiver eg.
I'm writing a concurrent server that's supposed to have a communication channel and a data channel.
The client initially connects to the communication channel to authenticate, upon successful authentication, the client is then connected to the data channel to access data.
My program is already doing that, and I'm using threads. My only issue is that if I try to connect another client, I get a "cannot bind : address already in use" error.
I have it this way:
PART A
Client connects to port 4567 (and enters his login info). A thread is spawned to handle the client (repeated for each client that connects). In the thread created, I have a function (let's call it FUNC_A) that checks the client's login info (don't worry about how the check is done), if successful, the thread starts the data server (listening on 8976), then sends an OK to the client, once received the client attempts to connect to the data server.
PART B
Once a client connects to the data server, from inside FUNC_A the client is accepted and another thread is spawned to handle the client's connection to the data server (hopefully everything is clear).
Now, all that is working fine. However, if I try to connect with second client when it gets to PART B I get a "cannot bind error: address already in use". I've tried so many different ways, I've even tried spawning a thread to start the data server and accept the client and then start another thread to handle that connection. Still no luck.
Please give me a suggestion as to what I'm doing wrong, how do I go about doing this or what's the best way to implement it.
Thank you
Your problem lies in the following: "...the thread starts the data server(listening on 8976)..."
If I understand you correctly, every time a client connects, you're trying to start listening on port 8976. The problem is, however, that there can be only one socket listening on a given port. When you try to start listening on the same port again, you get that error.
Therefore, you have two options:
Have the server listen on whatever port is free (just specify 0 when binding), and send the port number to the client, so that the client can connect to it.
Start the server only once, at the beginning, and have it accept client connections.
The second option, however, has a big problem: how are you going to tell one client from another? Therefore, I recommend going with the first option.
Some food for thought: what you're describing is pretty much exactly how FTP works. And FTP servers use the first option. Not coincidentally, perhaps? ;-)
I am writing a server in linux that is supposed to serve an API.
Initially, I wanted to make it Multi-threaded on a single port, meaning that I'd have multiple threads working on various request received on a single port.
One of my friends told me that it not the way it is supposed to work. He told me that when a request is received, I first have to follow a Handshake procedure, create a thread that is listening to some other port dedicated to the request and then redirect the requested client to the new port.
Theoretically, it's very interesting but I could not find any information on how to implement the handshake and do the redirection. Can someone help?
If I'm not wrong in interpreting your responses, once I create a multithreaded server with a main thread listening to a port, and creates a new thread to handle requests, I'm essentially making it multithreaded on a single port?
Consider the scenario where I get a large number of requests every second. Isn't it true that every request on the port should now wait for the "current" request to complete? If not, how would the communication still be done: Say a browser sends a request, so the thread handling this has to first listen to the port, block it, process it, respond and then unblock it.
By this, eventhough I'm having "multithreads" , all I'm using is one single thread at a time apart from the main thread because the port is being blocked.
What your friend told you is similar to passive FTP - a client tells the server that it needs a connection, the server sends back the port number and the client creates a data connection to that port.
But all you wanted to do is a multithreaded server. All you need is one server socket listening and accepting connections on a given port. As soon as the automatic TCP handshake is finished, you'll get a new socket from the accept function - that socket will be used for communication with the client that has just connected. So now you only have to create a new thread, passing that client socket to the thread function. In your server thread, you will then call accept again in order to accept another connection.
TCP/IP does the handshake, if you can't think of any reason to do a handshake than your application does not demand it.
An example of an application specific handshake could be for user authentication.
What your colleague is suggesting sounds like the way FTP works. This is not a good thing to do -- the internet these days is more or less used for protocols which use a single port, and having a command port is bad. One of the reasons is because statefull firewalls aren't designed for multi-port applications; they have to be extended for each individual application that does things this way.
Look at ASIO's tutorial on async TCP. There one part accept connections on TCP and spawns handlers that each communicate with a single client. That's how TCP-servers usually work (including HTTP/web, the most common tcp protocol.)
You may disregard the asynchronous stuff of ASIO if you're set on creating a thread per connection. It doesn't apply to your question. (Going fully async and have one worker-thread per core is nice, but it might not integrate well with the rest of your environment.)