I need to send a simple request to one of my server on defined intervals, let's say one every 2 seconds, in order to tell my server my machine's IP address(since I've dynamic one). I'm currently doing it in a while loop with a delay for std::system call for curl command with --silent option and redirecting rest to /dev/null. Something like this -
curl -s 'http://example.com' > /dev/null
The server currently parses the request and finds out the required IP address from it. Is there any other way to do this?
Another alternative would be sending a simple UDP datagram packet. The server can obtain the sender's address, upon receipt, equally well.
That requires a little bit less overhead than establishing a TCP connection. Of course, UDP offers no guarantee of deliverability, and an occasional UDP datagram would be lost; but since you're pinging the server regularly that should be fine. More importantly, however, is that a UDP sender's IP address is trivially forged. Whether or not this is an issue for your application is something that only you can determine.
If you're going to stick with TCP, one thing you can do is to establish a socket connection yourself. Let's examine what executing system(), just for the purpose of having curl do a dummy connection, involves:
forking a new child process.
the child process executing /bin/bash, passing it the command to parse.
Bash reading $HOME/.bashrc, and executing any commands in there. If your shell is something other than bash, the shell will have its own equivalent of a startup script to execute.
The shell forking a new child process.
The child process executing curl.
The loader finding all of the libraries that curl requires, and opening them.
curl now executes. Only then, after all this work, there will be code running to open a socket and attempt to connect to the remote host.
Steps 1 through 6 can be trivially skipped, simply by creating a socket, and connecting, yourself. It's not rocket science. socket(), connect(), close(), that's it. This task does not require HTTP. The server process only needs to socket(), bind(), listen(), and accept(), and then obtain the IP address from the connection. Done.
Related
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.
I need to accept multiple connections to the same port.
I'm using socket in C++, i want to do something like the SSH do.
I can do an ssh user#machine "ls -lathrR /" and run another command to the same machine, even if the first one still running.
How can i do that?
Thanks.
What you want is a multithreaded socket server.
For this, you need a main thread that opens up a socket to listen to (and waits for incoming client connections). This has to go into a while loop of some sort.
Then, when a client connects to it, the accept() function will unblock and at that point you need to serve the client request by passing on the request to a thread that will deal with it.
The server side will loop back and wait for another connection whilst the previous thread carries on its task.
You can either create threads as you need, or use a thread pool which might be more efficient (saving on time initialising new threads).
Have a look here for some more details.
Look for multithreaded server socket on the web, specifically bind(), listen() and accept() from the server side.
You need to read up on ::listen() and ::accept().
The former will set up your socket for listening. You then need a loop (probably in its own thread) which uses ::accept() which will return each time a new connection arrives.
That loop should then spawn a new thread to which you should pass the file descriptor received from ::accept() and then handles all I/O on that socket from thereon.
Old question is old, but I feel no one who answered understood the OP's question.
You're misunderstanding how ssh works. When you send multiple commands/multiple connections to a server over ssh, there is actually only ONE program on the server you're connecting to that is receiving all those commands.
Sshd (the ssh daemon) runs on the server, and is a multithreaded socket server (see fduff's answer). This is the only program that listens on port 22, and handles all incoming ssh connections by itself.
I'm Working in an embedded linux environment.
it launches a telnet daemon on startup which watches on a particular port and launches a program when a connection is received.
i.e.
telnetd -l /usr/local/bin/PROGA -p 1234
PROGA - will output some data at irregular intervals. When it is not outputting data, every X period of time it sends out a 'heartbeat' type string to let the client know that we are still active i.e. "heartbeat\r\n"
After a random amount of time, the client (use a linux version of telnet, launched by: telnet xxx.xxx.xxx.xxx 1234) will fail to receive the 'heartbeat\r\n'
The data the client sees:
heartbeat
heartbeat
heartbeat
...
heartbeat
[nothing, should have received heartbeat]
[nothing forever]
heartbeat is sent:
result = printf("%s", heartbeat);
checking result, it is always the length of heartbeat. Logging to syslog shows us that the printf() is executing with success at the proper intervals
I've since added in a tcdrain and fflush which both return success, but do not seem to help the situation.
Any help would be appreciated.
**UDPATE: got a wireshark capture from the server side. Very Clearly the heartbeat is being sent continuously. No Hicups, no delays. Found something interesting on the client though. The client in this test case (telnet on Ubuntu 9.04) seems to suddenly stop receiving heartbeat (as describes above). Wireshark confirms this, big pause in packets. Well, once the client had stopped receiving the heartbeat, pressing any keystroke (on the client) seems to trigger a spew of data from the client's buffer (all heartbeats). Wireshark on the client also shows this massive amount of data all in one packet.
Unfortunately I don't really know what this means. It this a line mode on/off thing? Line endings (\r\n) are very clearly coming through.
**Update 2: running netcat instead of telnetd, the problem is not reproducible.
The first thing I would do is get out Wireshark and try to find out if the server is truly sending the message. It would be instructive to run Wireshark at the server as well as third party PC. Is there anything different about the last heartbeat?
Edit. Well, that was an interesting find on your client.
It seems like there's some sort of terminal thing in the way. You may want to use the netcat program rather than telnetd. netcat is designed for sending arbitrary data over a TCP session in raw mode, without any special formatting, and it has the ability to hook up an arbitrary process to a socket. On a Windows machine you can use PuTTY in raw mode to accomplish the same thing.
It may still be worth examining traffic with a third party between your client and server. The kernel may be optimizing away writes to the network and internally buffering data. That's the only way to ensure that what see is what's really happening on the wire.
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? ;-)
Is there any method in c++/vc++/mfc so that I can verify whether remote machine is on network or not. I don't want to use ping command. I tried to use WSAConnect method but it takes lot of time in searching if remote machine is not on network. In that case application windoe freezes for long time. I need alternate way to verify remote machine netwotk connectivity. Plz help
You can check to see if a host name exists and if DNS can resolve an IP address for it, but this won't tell you if it's online. In order to determine if it's online, you must exchange data with the host. For this to happen the host must be listening on a port, and must send some sort of response.
Generally, the lowest common denominator for hosts is the ICMP packet - aka ping. You can write your own service in C++ to send these UDP packets, and detect a reply.
Some hosts and some routers disable ICMP to appear 'invisible'. If you know that your host accepts connections on a TCP port, you can attempt to create a tcp socket. For example, from a shell you can test using nc
nc -z google.com 80
Connection to google.com 80 port [tcp/http] succeeded!
If you do raw socket programming, you can attempt to connect to a host via, and then call select() with a short timeout.
If you don't want your app to block, use a thread.
If the only issue is that calling WSAConnect locks up your UI, you can try calling it in nonblocking mode.
Call WSAEventSelect to set the socket to nonblocking mode prior to calling WSAConnect. You then call WSAAsyncSelect or WSAEventSelect to check the status of the connection.
MSDN's page on WSAConnect has some remarks about nonblocking mode here.
You can use tracert command. Example:
tracert -w 1000 192.168.0.77
You can check if the machine is connected to a network, but without trying to transmit data to a site residing on the internet I don't think there is a way to check if that network is actually online. For example your end user might as well be connected to a DSL router which is not online at the moment.
You can use arping for it.
Also some smart switch can talk about attached host.