How Can get the interface list in C++ in linux ? - c++

I want to get my internet interface list in C++ in linux because my program need to down Or up the link but i dont know how get the interface to modifi it.

The system call you are looking for is getifaddrs. There is a brief example program on the man page.
Within the ifaddrs there is a bit flag field ifa_flags with which you can test whether the interface is up or down.

Read from /proc/net/dev
Full description in man proc:
/proc/net/dev
The dev pseudo-file contains network device status information. This gives the number of received and sent packets,
the number of errors and collisions and other basic statistics. These are used by the ifconfig(8) program to report
device status. The format is:
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 2776770 11307 0 0 0 0 0 0 2776770 11307 0 0 0 0 0 0
eth0: 1215645 2751 0 0 0 0 0 0 1782404 4324 0 0 0 427 0 0
ppp0: 1622270 5552 1 0 0 0 0 0 354130 5669 0 0 0 0 0 0
tap0: 7714 81 0 0 0 0 0 0 7714 81 0 0 0 0 0 0
This is a text file, each interface is a line... should be easy.
For example (no error checking... just printing the interface names)
#include <fstream>
#include <iostream>
int main() {
std::ifstream in("/proc/net/dev");
int c=0;
std::string line;
for(; std::getline( in, line ); c++)
{
if(c<2) continue; // skip header
std::size_t start=line.find_first_not_of(" "); // skip leading spaces
std::size_t end=line.find_first_of(":",start); // look for the ":"
std::cout << line.substr(start,end-start) << std::endl;
}
}

Related

Is there a better way to extract the n-th element of a stringstream than ignore in a loop?

I want to extract the n-th element of an std::istringstream. Right now I'm using a loop with std::istringstream::ignore, something like this:
std::istringstream linestream(line);
for (int i=0; i < n; i++) {
linestream.ignore(50, ' ');
}
linestream >> importantVariable;
The input is a process stat file on linux from /proc/$PID/stat and is comma seperated, but the fields do not have a fixed width (std::seekg won't work reliably here).
Is there a better way to do this? I was expecting something like an overloaded ignore method, that takes an argument which defines how many elements it should skip, instead of having to use a loop.
Edit: I've added information about the input stream.
Here is an example line:
1092 (avahi-daemon) S 1071 1071 1071 0 -1 1077936192 30 0 0 0 0 0 0 0 20 0 1 0 534 48205824 85 18446744073709551615 1 1 0 0 0 0 0 0 0 0 0 0 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0
Basically all said in the comments.
I just one to show an additional solution. The input data is anyway stored in a std::string. So you can directly extract it from there.
You can use iterators and std::next instead of loops.
The same works of course also for streams.
please see
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
#include <sstream>
const std::regex re(" ");
int main() {
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
std::string line{ "1092 (avahi - daemon) S 1071 1071 1071 0 - 1 1077936192 30 0 0 0 0 0 0 0 20 0 1 0 534 48205824 "
"85 18446744073709551615 1 1 0 0 0 0 0 0 0 0 0 0 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 "};
// 1. Extracting direcly from std::string
std::string entry24 = *std::next(std::sregex_token_iterator(line.begin(), line.end(), re, -1), 24);
std::cout << entry24 << "\n";
// 2. Putting in Stream and extracting from stream
// Stream solution
std::istringstream linestream(line);
entry24 = *std::next(std::istream_iterator<std::string>(linestream), 24);
std::cout << entry24 << "\n";
return 0;
}

boost asio async_receive_from() missing udp frames data retrieval when frames sent consecutive

The MVCE below simplified from real codebase shows the same issue.
The server continuously sends a "burst" of 5 UDP frames filled with 150 bytes of value 0xA5 with small or no delay in between. A pause of 1 second is made.
The client use the boost::asio async_receive_from() function in parallel of a 1 second timer.
The client works relatively well except when the delay between the UDP frames is "too" small. It seems that the correct size ( here 150 bytes ) is retrieved but the buffer/vector seems not to be updated.
5 x 150 bytes of UDP frames does not seem much.
Wireshark DOES see the complete and correct frames sent.
If I use a synchronous boost asio socket synchronous receive_from() I meet no issues
I tried maybe half a dozen times to dive into boost asio without much success in finding a single truth or rationale. Same posts on SO show very different code so that it is difficult to transpose them to the present code
Here are the code
client (client_with_timer.cc)
#include <iostream>
#include <vector>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
void asyncReadHandler( const boost::system::error_code& error, std::size_t bytesTransferred );
void timeoutHandler( const boost::system::error_code& error, bool* ptime_out );
size_t ReceivedDataSize;
std::string ReadError;
int main(int argc, char * argv[])
{
io_service io;
ip::udp::socket socket(io, ip::udp::endpoint(ip::udp::v4(), 1620));
size_t num = 0;
while (true)
{
std::vector<unsigned char> vec(1500);
ip::udp::endpoint from;
socket.async_receive_from(
boost::asio::buffer( vec ),
from,
boost::bind(
asyncReadHandler,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred ) );
bool timeout = false;
ReceivedDataSize = 0;
ReadError = "";
// Creating and starting timer (by registering timeout handler)
deadline_timer timer( io, boost::posix_time::seconds( 1 ) );
timer.async_wait(
boost::bind( timeoutHandler, boost::asio::placeholders::error, &timeout ) );
// Resetting IO service instance
io.reset();
while(io.run_one())
{
if ( timeout ) {
socket.cancel();
timer.cancel();
//Leave the io run_one loop
break;
}
else if ( (0 != ReceivedDataSize ) || (!ReadError.empty())) {
timer.cancel();
socket.cancel();
std::cout << "Received n°" << num++ << ": " << ReceivedDataSize << "\r" << std::flush;
if (0 != ReceivedDataSize )
vec.resize(ReceivedDataSize);
if (!ReadError.empty())
std::cout << "Error: " << ReadError << std::endl;
bool result = true;
for ( auto x : vec )
if ( 0xA5 != x ) { result = false; break; }
if ( false == result ) {
std::cout << std::endl << "Bad reception" << std::endl << std::hex;
for ( auto x : vec )
std::cout << (int)x << " ";
std::cout << std::dec << "\n";
}
//Leave the io run_one loop
break;
}
else {
//What shall I do here ???
//another potential io.reset () did not bring much
}
}
}
return 0;
}
void asyncReadHandler( const boost::system::error_code& error, std::size_t bytesTransferred )
{
// If read canceled, simply returning...
if( error == boost::asio::error::operation_aborted ) return;
ReceivedDataSize = 0;
// If no error
if( !error ) {
ReceivedDataSize = bytesTransferred;
}
else {
ReadError = error.message();
}
}
void timeoutHandler( const boost::system::error_code& error, bool* ptime_out )
{
// If timer canceled, simply returning...
if( error == boost::asio::error::operation_aborted ) return;
// Setting timeout flag
*ptime_out = true;
}
Here is the server (server.cc) so that you do not have to roll your own
#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <unistd.h>
using namespace boost::asio;
int main(int argc, char * argv[])
{
io_service io;
ip::udp::socket socket(io, ip::udp::endpoint(ip::udp::v4(), 0));
std::vector<char> vec(150,0xA5);
#if 1
int separator = 1 * 1000;
#else
int separator = 0;
#endif
while (true)
{
socket.send_to(buffer(vec), ip::udp::endpoint(ip::udp::v4(), 1620));
if ( separator ) usleep(separator);
socket.send_to(buffer(vec), ip::udp::endpoint(ip::udp::v4(), 1620));
if ( separator ) usleep(separator);
socket.send_to(buffer(vec), ip::udp::endpoint(ip::udp::v4(), 1620));
if ( separator ) usleep(separator);
socket.send_to(buffer(vec), ip::udp::endpoint(ip::udp::v4(), 1620));
if ( separator ) usleep(separator);
socket.send_to(buffer(vec), ip::udp::endpoint(ip::udp::v4(), 1620));
usleep(1000*1000);
}
return 0;
}
I compiled both with the naive commands below:
g++ client_with_timer.cc -std=c++11 -O2 -Wall -o client_with_timer -lboost_system
g++ server.cc -std=c++11 -O2 -Wall -o server -lboost_system
It produces output like below when delay is too small
nils#localhost ASIO_C]$ ./client_with_timer
Received n°21: 150
Bad reception
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Received n°148: 150
Bad reception
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Received n°166: 150
Bad reception
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Received n°194: 150
How to correct the client code to avoid missed frames ?
Any hint for a better understanding of boost asio rationale is welcome
I think in your code are data races.
If timer is expired (timeout occures) before read operation is completed below code is executed:
if ( timeout ) {
socket.cancel();
timer.cancel();
//Leave the io run_one loop
break; // [1]
}
you are breaking from while loop, socket.cancel() cancels asynchronus read operation, its handler with operation_aborted error is queued and waits for processing in event loop. Because you jumped from while loop, run_one is not invoked, and this handler is still in queue.
io_service.reset() doesn't clear queue. Handler for aborted operation is still there. And waits to be invoked. reset() only sets stopped flag of io_service to false, then handlers can be processed by calls run_one, one .. methods, you are using reset to restore processing handlers from queue.
So we have unprocessed handler in queue, in main while loop new vector vec is created, all its elements are initialized to 0. async_receive_from started (it is reading into vec and set ReceivedDataSize in its handler), then reset is called, run_one can process handler and invokes handler for aborted operation! and you are testing ReceivedDataSize and vec for aborted operation... but you should do it for the last started async operation.
I would rewrite clause with timeout to:
if ( timeout ) {
socket.cancel();
timer.cancel();
} // no break
after removing break we guarantee that aborted operation is processed by run_one and there is no outstanding handler to be invoked when new async operation is started.
After this modifcation I have not seen bad reception while testing your code.
EDIT
Regarding your comment, yes the other break statement should also be removed from the code.
Output of the program is unpredictable because you are starting async operations which takes reference to local variable (vec is modified by async_receive_from), handler is queued, local variable is destroyed and later the handler is called from io_service while vec has been already destroyed.
You can test the code below, and see what happens:
boost::asio::io_context io; // alias on io_service
boost::asio::system_timer t1{io};
t1.expires_from_now(std::chrono::seconds(1));
boost::asio::system_timer t2{io};
t2.expires_from_now(std::chrono::seconds(1));
boost::asio::system_timer t3{io};
t3.expires_from_now(std::chrono::seconds(1));
t1.async_wait ([](const boost::system::error_code& ec){ cout << "[1]" << endl;});
t2.async_wait ([](const boost::system::error_code& ec){ cout << "[2]" << endl;});
t3.async_wait ([](const boost::system::error_code& ec){ cout << "[3]" << endl;});
// 3 handlers are queueud
cout << "num of handlers executed " << io.run_one() << endl; // wait for handler, print 1
io.reset(); // RESET is called
cout << "num of handlers executed " << io.run_one() << endl; // wait for handler, print 1
io.reset(); // RESET is called
cout << "num of handlers executed " << io.run_one() << endl; // wait for handler, print 1
cout << "executed: " << io.poll_one() << endl; // call handler if any ready, print 0
we are calling io_service::reset but all handlers are executed. After removing breaks from your code, you ensure that all handlers will be performed, and it guarantees that the local data are valid when these handlers are called.

Setting the number of edges in igraph_erdos_renyi_game c++

I would like to create a directed network graph using igraph c++ in which each node is randomly connected to exactly n other distinct nodes in the network (i.e. excluding connections to itself, and loops/multiple edges to the same loop). I was thinking of using the method igraph_erdos_renyi_game, but for some reason I do not get the desired degree distribution. In particular, if I set the arguments like this:
igraph_erdos_renyi_game(&g, IGRAPH_ERDOS_RENYI_GNM, n, m, true, false);
with n = 5, m = 1, I get this Adjacency Matrix (e.g.):
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
0 0 0 0 0
If I use igraph_k_regular_game(&g, n, m, true, false) instead, I get exactly the desired outcome, namely (e.g.):
0 0 0 0 1
1 0 0 0 0
0 0 0 0 1
0 1 0 0 0
0 0 0 1 0
So to summarize, I would like for each node to have 1 edge to n randomly selected agents. Am I misinterpreting the way the Erdos-Renyi method works, or am I passing the wrong arguments?
m is the total number of edges in erdos_renyi_game(). So just use k_regular_game(), it does exactly what you want.

Tellg returning unexpected value

I have a function which reads lines from a file. But before reading it returns the address from where its going to read the next line.
my function is:
void print()
{
int j=0;
string a,b,c,d,e;
ifstream i("data.txt");
cout<<setw(15)<<left<<"Hash Value"<<setw(15)<<left<<"Employee Name"<<setw(15)<<left<<"Employee ID"<<setw(15)<<left<<"Salary"<<setw(15)<<left<<"Link"<<endl;
while(j<10)
{
j++;
cout<<i.tellg()<<endl;
i>>a>>b>>c>>d>>e;
cout<<setw(15)<<left<<a<<setw(15)<<left<<b<<setw(15)<<left<<c<<setw(15)<<left<<d<<setw(15)<<left<<e<<endl;
}
i.close();
}
The file it is reading from is data.txt:
0 --- 0 0 -1
1 --- 0 0 -1
2 --- 0 0 -1
3 --- 0 0 -1
4 --- 0 0 -1
5 --- 0 0 -1
6 --- 0 0 -1
7 --- 0 0 -1
8 --- 0 0 -1
9 --- 0 0 -1
And the output I am getting is:
Hash Value Employee Name Employee ID Salary Link
0
0 --- 0 0 -1
81
1 --- 0 0 -1
157
2 --- 0 0 -1
233
3 --- 0 0 -1
309
4 --- 0 0 -1
385
5 --- 0 0 -1
461
6 --- 0 0 -1
541
7 --- 0 0 -1
617
8 --- 0 0 -1
693
9 --- 0 0 -1
Every line is of length 76 characters. So everytime the address printed should increase by 76.
But i dont understand whats going on when the 2nd line is printed[hash value 1], and the 7th line is printed [hash value 6].
Can someone please help me with this?
A couple of things:
First and foremost, you're not reading line by line, so there
is no reason to assume that you advance the number of characters
in a line each time through the loop. If you want to read line
by line, use std::getline, and then extract the fields from
the line, either using std::istringstream or some other
method.
The result of tellg is not an integer, and when converted to
an integral type (not necessarily possible), there is no
guaranteed relationship with the number of bytes you have
extracted. On Unix machines, the results will correspond, and
under Windows if (and only if) the file has been opened in
binary mode. On other systems, there may be no visible
relationship what so ever. The only valid portable use of the
results of tellg is to pass it to a seekg later; anything
else depends on the implementation.
How do you know that each line contains exactly 76 characters?
Depending on how the file was produced, there might be a BOM at
the start (which would count as three characters if the file in
encoded in UTF8 and you are in "C" locale). And what about
trailing whitespace. Again, if your input is line oriented, you
should be reading lines, and then parsing them.
Finally, but perhaps the most important: you're using the
results of >> without verifying that the operator worked. In
your case, the output suggests that it did, but you can never be
sure without verifying.
Globally, your loop should look like:
std::string line;
while ( std::getline( i, line ) ) {
std::istringstream l( line );
std::string a;
std::string b;
std::string c;
std::string d;
std::string e;
l >> a >> b >> c >> d >> e >> std::ws;
if ( !l || l.get() != EOF ) {
// Format error in line...
} else {
// ...
}
}
Outputting tellg still won't tell you anything, but at least
you'll read the input correctly. (Outputting the length of
line might be useful in some cases.)

Loading Data from File to Data Structure in C++ and Interpreting It

Okay so this code is killing me.
My goal is to read data from a file where the data is separated by commas, then load that data into an array of structures that is supposed to be a list of "theater seats". The theater seats have certain characteristics, such as "location", "price", and "status". Price is self-explanatory. Location deals with the row and seat number of the "Seat". And status pertains to whether or not it's sold. After that, I have to interpret the data that I pulled from the data file to make a display THAT CAN be easily manipulated by the user if they input a certain choice. But that's not what I'm getting at in this question.
My question is, what would be the best method to load my data structures from the data file?
Let me show you a bit of the data file that I'm reading from.
1, 1, 50, 0
1, 2, 50, 0
1, 3, 50, 0
1, 4, 50, 0
To explain the data file, the first number is the "row", second number is the seat number in that row, the third number is the price, and the final number ("0") stands for the seat being unsold. Had the seat been purchased, the final number would be 1.
Now, here's my code.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <cstdio>
#include <conio.h>
using namespace std;
enum seatDimensions{ROWS = 10, SEATS_PER = 16};
//Structures
struct Location
{
int row;
int seatNumber;
};
struct Seat
{
Location seat_location[160];
double ticketPrice;
int status;
int patronID;
};
//GLOBALS
const int MAX = 16;
int main()
{
//arrays for our data
Seat seatList[160];
//INDEX
int index = 1;
//filestream
fstream dataIn;
dataIn.open("huntington_data.dat",ios::in);
if(dataIn.fail()) //same as if(dataIn.fail())
{
cout << "Unable to access the data file." << endl;
return 999;
}
string temp;
getline(dataIn,temp,',');
seatList[index].seat_location[index].row = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].seat_location[index].seatNumber = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].ticketPrice = atof(temp.c_str());
getline(dataIn,temp,'\n');
seatList[index].status = atoi(temp.c_str());
while(!dataIn.eof() && index < MAX)
{
index++;
getline(dataIn,temp,',');
seatList[index].seat_location[index].row = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].seat_location[index].seatNumber = atoi(temp.c_str());
getline(dataIn,temp,',');
seatList[index].ticketPrice = atof(temp.c_str());
getline(dataIn,temp,'\n');
seatList[index].status = atoi(temp.c_str());
}
getch ();
return 0;
}
Now from here, I have to display whether or not the seats are TAKEN or not.
The display should look like this, since none of the seats are taken yet.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 // 16 across
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
// 10 deep
I know I'm not inputting my data in correctly, because I cannot seem to get this display no matter how I try to cout it. If you can tell where I'm going wrong, please tell me. Any suggestions would be amazing.
Also, if you have any questions for me, just ask. I tried to be as specific as possible considering the question, but I know that it's still pretty vague.
Please help.
EDIT: Thanks to those who answered my question. I ended up going a very different route with my data structure, but pulled a lot from the answers.
You have the problem that each seat has a position in an array and then has an array of positions:
You need:
Location seat_location[160];
changed to:
int seat_row;
int seal_num;
then:
seatList[index].seat_location[index].row = atoi(temp.c_str());
becomes:
seatList[index].seat_row = index / COLS ;
seatList[index].seat_num = index % COLS ;
You may also like to consider actually arranging your data into a 2D array of the same dimensions as your seating.
BTW From my C background I would suggest reading the whole line and using sscanf, e.g.:
char temp[255]; // Use an appropriate maximum line length +3 for \r\n\0
fgets(dataIn, &temp);
sscanf(temp, "%d, %d, %d, %d", &.....
You could also consider implementing this with a regular expression.
Write a function that gets string of input and splits it into items:
std::vector<std::string> splitLine( const std::string &str );
Implement and debug it with string like "1, 1, 50, 0", make sure it returns vector of string with each number as separate element. Then read input line by line, split and convert each string to number separately. You will simplify the code and it will be much easier to make it work.
is it an assignment?
i guess the way you are organizing your data in structure needs to be changed.
Take a structure maybe like this
struct Seat{
double ticketPrice;
int status;
int patronId;
}
and have a two dimensional array like this
Seat seatList[10][16];
first dimension is (row number-1), second dimension is (seat number-1)
and read your data from file like this
string temp;
getline(dataIn,temp,',');
int row = atoi(temp.c_str());
getline(dataIn,temp,',');
int seatNumber = atoi(temp.c_str());
getline(dataIn,temp,',');
//check row and seatnumber > 0
seatList[row-1][seatNumber-1].ticketPrice = atof(temp.c_str());
getline(dataIn,temp,'\n');
seatList[row-1][seatNumber-1].status = atoi(temp.c_str());
Use two simple for loops to print your output from these structures.