I'm currently working on a C++ application that communicates with my browser using WebSockets. The connection is only local, there won't ever be any non-local socket.
Currently my C++ code looks like that (just for an example):
while (true) {
WebSocket *socket = server->accept () ;
socket->read (buffer, 256) ;
}
And my javascript code:
var socket = new WebSocket ("ws://localhost:4564") ;
socket.onopen = function () {
socket.send("Hello my name is Holt!");
} ;
As you can see, I'm waiting for a packet that should be sent as soon as the connection is openned. So I got 2 questions:
First, are there any way to send this information directly inside the connection? (I think no, so it's why my second question comes for...)?
Second, knowing that the connection is local, is that possible that the server accept the socket without being able to retrieve the packet after?
To add a bit more information, the current C++ application is based on Qt 5.3 with the QtWebSockets module and the javascript code is a Google Chrome extension that will run a script on specific websites.
Thanks for you help!
After you establish websocket connection between client and server, in client, when connection is alive, you can call socket.send() when you want to send data to server.
Even connection local, server is still need wait and receive data, which is a full TCP/IP data transfer process.
Related
I am currently writing a server application that should instruct multiple clients.
I am unsure about the concept i have designed and would like to receive feedback on it.
There are several identical clients that record and process sensor data. In addition, the results are sent to the server so that the server can react if necessary and send new parameters to the client.
The client should continue to work after the connection has ended and try to reconnect at the same time. If there is no connection, data do not have to be transmitted subsequently.
My concept is as follows:
The client logs on to the server.
The client requests an initialization -> server ok.
The client requests parameter A -> server sends parameter
The client requests parameter B -> server sends parameter
...
The client requests parameter Z -> server sends parameter
The client sends initialization finished -> server says ok
endless loop
Server queries measured value X -> client sends measured value
Server sends parameter Y -> client says ok.
So first the client is the master and asks for the initialization parameters it needs, then the server and client swap roles and the server becomes the master.
Should the connection break, the client should reconnect to the server. but would then with the command:
The client sends initialization finished -> server says ok
start so that the initialization is skipped.
The request of parameters runs as follows:
Infinite loop
Send (command)
Timout = 1 second
Receive
if (! Timout)
break
so i send the command and wait a little, if no answer comes i send the command again. this is shown here in abbreviated form. I wrote it in c ++ and I use several state machines. The state machines naturally also catch errors when the connection is interrupted and jump back to the initialization status ...
Since this is a multi-client application, I find it a little difficult. it runs as a single client. I have a class client in which a state machine and a socket are stored. the instance runs in a separate thread.
My problem now is, if the connection is lost, how can I establish a new connection (from an old client) to its instance (state machine). i would do this over some id comparison. so that the client sends his id first of all. (maybe also mac address ???)
I currently keep the connections to all clients open at all times. is that state of the art? or should you send a command, wait for an answer and close the connection again and then reconnect if necessary?
Many Thanks
Once TCP connection is established
each side can send for data.
Just that you have to get write -> read sequence correct.
This can be easily implemented using non blocking socket IO.
"My problem now is, if the connection is lost, how can I establish a
new connection (from an old client) to its instance (state machine). i
would do this over some id comparison. so that the client sends his id
first of all. (maybe also mac address ???)"
One solution is each client has a UUID, Client must tell server every time it connects its ID , server can keep a map of UUID vs client socket connection.
If Client is lost server can delete the mapping. Both server & client can detect lost connection that should not be a problem.
Short Version: If I have an open tcp socket running in an ioserive what happens if I stop the service? Should data continue to queue in the tcp socket (assuming the server continues to send data and there has been no disconnect)? If so can I retrieve that data by resetting and restarting the ioserive?
Long Version: I'm trying to put a blocking interface around my asio based tcp socket API.
The user initially connects using the API which opens a socket to a server.
For each subsequent API call the ioservice is reset and started, then data is sent to the server using the tcp socket with boost::asio::write and a response waited on. The response from the server is handled using async_read_until. When the response is received the handler is invoked, the ioservice stopped and the original blocking API call releases back to the client, with the data from the server. This works OK for request-response type commands. In summary:
API blocking call
ioservice resets and starts
tcp packet sent to server
server responds
handler invoked
ioservice stopped
API call released and data passed to user
Another command is a request-response that starts a broadcast from the server that updates an internal cache on the client-side. The idea is that the user accesses this cache with another API function after an initial attempt to refresh it using an ioservice start-stop process similar to above. However, before this attempt the code checks to see if any data is available on the socket using one of the options below:
bool is_data_available() {
//boost::asio::socket_base::bytes_readable command(true);
//socket_->io_control(command);
//return command.get() > 0;
return socket_->available() > 0;
}
There is never any data, even though the server has logged as having sent the data.
So summary for the broadcast:
Successfully executes the previous list of bullet points to start the broadcasting
Observe that the server has sent the data
Call above code block to see if any data in the socket (note that the service has not been started at this point)
Never any data
I'm trying to code a simple actionscript tcp client, which is to send data to a c++ tcp server. I'm new to actionscript and I'm using sample code from adobe (see link below) for the client. I am able to make a connection and send data, but the data is only available at the server when the object is unloaded at the client side (hence closing the socket I guess). I tried using a c++ client, and the data is immediately available at the server, so I must be missing something on the client side. Maybe I need to append some kind of termination/marker sequence?
Actionscript code sending data over tcp:
private function tcpConnect():void
{
var customSocket:CustomSocket = new CustomSocket("127.0.0.1", 5331);
customSocket.timeout = 100;
socketWrite(customSocket, 53);
socketWrite(customSocket, 54);
socketWrite(customSocket, 55);
socketWrite(customSocket, 56);
}
private function socketWrite(sock:CustomSocket, b:int):void
{
sock.writeByte(b);
sock.writeByte(0);
sock.flush();
}
C++ tcp server: http://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx
Actionscript tcp client: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html#includeExamplesSummary
Right after connection to the server the client socket will send a request for the crossdomain file, it will look like this
<policy-file-request/>
You probably have seen this in the server logs
At this time the server should send the file back via the socket connection.
Once the client gets the file it will probably close the connection.
Now you need to restart the connection and send all your data without hinderance.
I am writing a client-server application using sockets in C++.
The protocol for communications is essentially:
The client connects to the server.
The client "sends" an ASCII command to the server.
The server executes the command remotely, and gets the results, and sends the results back to the client.
the results can be multiple megabytes of data. Once all the results are sent to the client, I would like the server to signal the client that it's done.
Is the best way to closesocket(), or should it send a message that indicates to the client that there are no more results, and the client can decide whether to close the socket or not? The drawback with closing the socket is that the client will need to establish a new connection if it wants to execute another command, but the drawback of sending a message back from the server is that the client needs to scan every recv to determine if the results are done.
Which is the best practice?
I would take a slightly lateral approach:
Client sends command to server
Server send size of response and then the real response
Client can issue new command / close connection
In this way the client knows how much to read and can decide whether to close the connection or not.
I am working on a project where a partner provides a service as socket server. And I write client sockets to communicate with it. The communication is two way: I send a request to server and then receive a response from server.
The problem is that I send the data to the server but apparently the server cannot receive the data.
From my side I just use very simple implementation just like the example from http://www.linuxhowtos.org/C_C++/socket.htm
#include <sys/socket.h>
socket_connect();
construct_request_data();
send(socket, request_data, request_length, 0/*flag*/); // I set flag as 0
// now the server should receive my request and send response to me
recv(socket, response_data, response_length, 0);
socket_close();
And it seems that the server socket is implemented with a "binding" to std::iostream and it is buffered stream. (i.e. the socket send/recv is done in iostream::write/read.)
server_socket_io >> receive_data;
server_socket_io << response_data;
Btw, I got a test client from my partner and it is wrapped in a iostream as well. The test socket client can communicate with the server without problem, but it must do iostream::flush() after every socket send.
But I want to just keep it simple not to wrap my socket client in iostream.
I just wonder whether the buffered iostream results in the problem: the data is not processed since the data the client socket sent is just in very small amount and still buffered.
Or could it be my problem? how can I know if I really send out the data? does my client socket also buffer the data?
I have tried some "bad" workaround with TCP_NODELAY but it didn't help!
How can I solve the problem? from client side? or server side?
Should I close the socket after sending request and before receiving response, so that the data will be "flushed" and processed?
or should I wrap my socket in iostream and do flush?
or the server socket should use a "unbuffered" stream?
thanks for any suggestion and advice!
Further to Jay's answer, you can try any network packet sniffer and check whether your packets are getting to the server or not. Have a look at wireshark or tcpdump.
Let's use "divide and conquer" to solve the problem.
First, does the server work?
From your code look up the port number that your server is listening on.
Start your server program.
Run the following command line program to see if the server is really listening:
netstat -an -p tcp
It will produce a list of connections. You should see a connection on your selected port when the server is running. Stop the server and run the command again to ensure the port is no longer in use.
Once you've verified the server is listening try to connect to it using the following command:
telnet your-server-address-here your-port-number-here
telnet will print what your server sends to you on the screen and send what you type back to the sever.
This should give you some good clues.
I had a similar issue once before. My problem was that I never 'accepted' a connection (TCP) on the server inorder to create the stream between server/client. After I accepted the connection on the server side, everything worked as designed.
You should check the firewall settings for both systems. They may not be passing along your data.