multi sockets in boost asio? - c++

I wanted to make a chat server using boost::asio and as the program gets more complicated and difficult for myself to read, I was wondering if it is possible to use several sockets in the same client and on server side?
If I can't make myself quite clear to you, for example, in my server side I have int and string variables and I want to send them in different sockets NOT effecting to each other.
Well... int variable is sent through socket1 and string is through socket2. The same thing with a client side that it should "know" from which socket int is "coming" and from which string. If this is possible I would be very glad to see some examples :)
Thank you in advance!

the program gets more complicated and difficult for myself to read
You might want to refactor a bit. Even large code should be easy to read and understand.
I have int and string variables and I want to send them in different sockets NOT effecting to each other.
You don't create a new socket for each data-type you want to send. Add a proper header to your message and parse the received data-type with error checking.
For instance (simplified case):
std::string tx = "12345678Test";
std::stringstream ss(tx);
int num;
ss >> num;
std::string s;
ss >> s;

Related

How to transfer serialized data to the server and deserelize it

I use the enet library to write the client and server side of the code, and also decided to use the boost library to serialize the data. I used something like this code to send data and serialize it
char message_data[80] = "somedata";
std::stringstream ss;
boost::archive::binary_oarchive oa{ ss };
oa << message_data;
SendPacket(peer, ss.str());
and something like this code for getting data and deserializing it
std::string deser_data;
std::string some_data = (char*)event.packet->data;
std::stringstream ss(some_data);
boost::archive::binary_iarchive ia{ ss };
ia >> deser_data;
But this code does not work, I think it is due to incorrect use of stringstream, but this is not accurate
Is there some reason you want to use a binary (non-portable, change-intolerant) representation? JSON has become a bit of a standard. Be that as it may...
I would add some debug. What length are you writing? What length are you reading? If you dump the buffers, are they identical on client and server?
Does the code work if you do it all inline (no network involved)? That is, can you write a unit test to do both the client and server side where you construct an object, serialize it, deserialize into another object, and then compare them?
I'd start with that.
Sorry, this isn't a proper answer, but it's too long for a simple comment.

Turn stream into function argument to use Telnet and Ncurses

Hello fellow programmers.
I'm developing a C/C++ program with sockets that are supposed to connect to the server via Telnet.
To send text and ANSI codes to the Telnet remote terminal I'm using this funcion:
void writeline(int socketfd, string line)
{
string tosend = line + "\n";
write(socketfd, tosend.c_str(), tosend.length());
}
Is there a way to create a stream object like cout, cerr, clog or even a FILE (from C) that sends everything it gets to a function?
For example:
clientout << "Hello World";
would call something like this:
writeline(clientout.str()); //or alike
I did something like this last year when I programmed a microprocessor (with AVR) and redirected stdout into a function that sent everything to the USART connection. I was hoping I could do something like that now.
This is how I did it then:
static int usart_putchar(char c, FILE *stream)
{
while ( !(UCSR0A & (1<<UDRE0)) );
UDR0 = c;
return 0;
}
static FILE usart_stream = FDEV_SETUP_STREAM(usart_putchar, NULL, _FDEV_SETUP_WRITE);
int main()
{
//(...)
stdout = &usart_stream;
//(...)
}
I'm interested in this because, besides being an easier way to print into the remote terminal, I need a stream for even thinking about using ncurses with my program. To use it, I need this function which needs a stream for input and another for output.
I apologize for the long question.
Thank you in advance.
Yes, it's possible to do this, but it's quite a bit of work.
Basically, you have to implement a subclass of std::streambuf that implements std::streambuf's virtual methods to read and write from the socket directly, or call the wrapper functions you showed in your question. It's not really a lot of work, it's only a handful of virtual methods, but you have to understand their obscure semantics, and implement them correctly, 100%. No margin for error.
Once you have your std::streambuf subclass, you can then instantiate a std::istream, std::ostream, and/or std::iostream (which have a constructor that takes a pointer to a std::streambuf).
Now, you have your stream that reads and/or writes to the socket.
Could you use boost asio?
See example of using posix::stream_descriptor to implement a chat application http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/chat/posix_chat_client.cpp

Reading binary data in memory into a stringstream and stream this over a socket

I would like to know if it is possible to, for instance, take a piece of data in memory, read it into an output stringstream (as binary data) and write this onto a socket for a client application to process.
The problem I run into while attempting this is the following:
Example:
char name[1024] = "Test";
std::ostringstream message (std::stringstream::out | std::stringstream::binary);
len = strlen(name);
message.write(reinterpret_cast<const char*>(&len), sizeof(int));
message.write(test, len*sizeof(char));
I want to write this stringstream to the socket with all of the data in it, but the problem is this: The stringstream write only executes the first time, in this case writing 4 (the length of the string) and none of the subsequent writes. Am I missing something here?
If this is not the best way to do it, what would be the best way to accomplish this? This is partly to reduce file I/O for cached memory snapshots.
Thanks in advance..
Your code (with minor fixes) appears to work for me, so you might check to be sure that you are correctly handling the buffered binary data, i.e. you do not assume that the std::string contains a string.

Linux C++ write string to COM port, read back response?

I am trying to write to the /dev/ttyACM0 port. In the command line shell I can write the string ":35\n" to the sensor I have plugged in to that port, and via putty listening on the port I can see it responds and gives me the data I am asking for (compass data).
I want to write a driver in C++ that writes this string to that port and reads in the response returned. I have looked online but have been unsuccessful in writing this. I feel like it should be an easy task. I wouldn't think writing to the ttyACM port would be any different than writing to a ttyCOM or ttyS port. Can anyone give me an example of this? I wouldn't think it'd be more than 5 lines of code.
Thank you for any help.
As requested, five lines of code:
#include <fstream>
std::fstream file("/dev/ttyACM0");
file << ":35" << std::endl; // endl does flush, which may be important
std::string response;
file >> response;

sending a serialized type over a boost-asio socket connection using boost serialization

I am trying to send 1kb of data from a "server" to a "client", but I just can't get it right.
There are a few things that I NEED to do in this:
1) Need to use boost-asio sockets to transfer the data
2) Need to serialize a type I created (Packet) that will contain the data as a string or char*
Here is what is going on:
First, I get 1kb of data from a sample text file on the server. I get this and put it into the Packet type that I created. I have defined the data field in Packet to hold this data as a std::string. (I tried char* but it didnt work well - see next paragraph).
Second I serialize it using boost text_oarchive . I have no problems serializing the Packet type if it just contains a string, but what I really want is a way to serialize it with the data type being a char array (so that it works better with the socket below)
Third, I send it over a boost asio socket. Here I have a problem because I can't find a way to send a std::string over the socket connection. Everything I see as examples and in the documentation need a buffer using some type of char* and not a string.
its just a headache. can you help?
Everything I see as examples and in the documentation need a buffer
using some type of char* and not a string
That is correct, though it's quite simple to do using Boost.Serialization and Boost.Asio. You can serialize using a text_oarchive to a boost::asio::streambuf then send the resulting stream buffer contents using a socket.
See this question and my answer to that question for a more complete example.