Multiple messages in a tcp buffer - c++

I am actually programming a simple server and it's client in c++ using the tcp protocol. As this is to be integrated in a multiplayer game, every client has to send data extremely fast.
Issue: The server's buffer sometimes gets multiple messages in it.
I tried various things like putting off nagle's algorithm but I didn't manage to fix this problem. Here's the server's code :
#ifdef __linux__
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <arpa/inet.h>
#define SOCKET int
#define SOCKADDR_IN struct sockaddr_in
#endif
#ifdef _WIN32
#include <winsock2.h>
#endif
#include <cstdio>
#include <iostream>
#include <thread>
#include <vector>
#include <string>
#include "server.h"
#include "../../Logger/logger.h"
#include "../../AltisCraft.fr/Map/map.h"
#include "../../StringPlus/string_plus.h"
#include "../../AltisCraft.fr/Map/User/User.h"
void connectEvent(), receive(), sendAllUsers(string), closeConnectio(),manageMsg();
vector<SOCKET> clients;
vector<thread> clientsThreads;
vector<string> msg;
SOCKET socketId, newSocketId;
SOCKADDR_IN source;
thread connection;
char buffer[65535] = {0};
int position;
// TODO: crypt every data sendLog/receive
// TODO: whitelist ip serv
// TODO: Auth system
// TODO: timer with packet ? (double receive...)
int sendLog(SOCKET s, const char* c, int i0, int i1)
{
log("Send:");
log(c);
send(s, c, i0, i1);
}
void initializeNetwork()
{
#ifdef _WIN32
WSADATA initWin32;
WSAStartup(MAKEWORD(2, 2),&initWin32);
#endif
socketId = socket(AF_INET, SOCK_STREAM, 0);
source.sin_family = AF_INET;
source.sin_addr.s_addr = INADDR_ANY;
source.sin_port = htons(33333);
bind(socketId, (struct sockaddr*)&source, sizeof(source));
connection = thread(&connectEvent);
connection.join();
closeConnection();
}
void connectEvent()
{
int error;
while(1)
{
error = 99;
while(error != 0)
{
error = listen(socketId, 1);
}
#ifdef _WIN32
int tempo = sizeof(source);
newSocketId = accept(socketId, (struct sockaddr*)&source, &tempo);
clients.push_back(newSocketId);
#endif
#ifdef __linux__
socklen_t tempo;
newSocketId = accept(socketId, (struct sockaddr *)&source, &tempo);
clients.push_back(newSocketId);
#endif
clientsThreads.push_back(thread(&receive));
}
}
void receive()
{
int val = 1;
position = clients.size() - 1;
bool connected = 1;
while(connected)
{
buffer[65535] = {0};
if(recv(clients[position], buffer, 1515, 0) > 0)
{
string msg = buffer;
bool isEmpty = false;
log(string(inet_ntoa(source.sin_addr)) + ": " + msg);
if(startsWith(msg, "Connect "))
addUser(replace(msg, "Connect ", ""));
else if(msg == "MAJ Map")
{
log(elements);
string toSend = "MAJ Map\n" + elements;
sendLog(clients[position], toSend.c_str(), strlen(toSend.c_str()), 0);
}
else if(startsWith(msg, "MAJ User ")) /// optimize: don't sendLog pos to player who sendLog
{
msg = replace(msg, "MAJ User ", "");
if(startsWith(msg, "Pos "))
{
msg = replace(msg, "Pos ", "");
vector<string> elements = split(msg, " ");
User user = *getUserByName(elements[0] + " " + elements[1]);
user.updateView(user.getView().updatePosition(Position(convertStrToDouble(elements[2]), convertStrToDouble(elements[3]), convertStrToDouble(elements[4]))));
}
else if(startsWith(msg, "ViewAngle "))
{
msg = replace(msg, "ViewAngle ", "");
vector<string> elements = split(msg, " ");
User user = *getUserByName(elements[0] + " " + elements[1]);
user.updateView(user.getView().updateViewAngle(ViewAngle(convertStrToDouble(elements[2]), convertStrToDouble(elements[3]))));
}
}
else
sendAllUsers(string(string(inet_ntoa(source.sin_addr)) + ": " + msg).c_str());
}
else
connected = 0;
}
shutdown(clients[position], 2);
for(int i=0;i<msg.size();i++)
cout << msg[i] << endl;
#ifdef _WIN32
closesocket(clients[position]);
#endif
#ifdef __linux__
close(clients[position]);
#endif
clients.erase(clients.begin() + position);
}
void sendAllUsersWithoutOne(string msg, string name)
{
for(int j = 0; j < (int)clients.size(); j++)
{
// only linux here (MSG_DONTWAIT)
#ifdef __linux__
if(recv(clients[j], NULL, 1, MSG_PEEK | MSG_DONTWAIT) == 0)
{
clients.erase(clients.begin() + j);
continue;
}
#endif
sendLog(clients[j], msg.c_str(), strlen(msg.c_str()), 0);
}
}
void sendAllUsers(string msg)
{
for(int j = 0; j < (int)clients.size(); j++)
{
// only linux here (MSG_DONTWAIT)
#ifdef __linux__
if(recv(clients[j], NULL, 1, MSG_PEEK | MSG_DONTWAIT) == 0)
{
clients.erase(clients.begin() + j);
continue;
}
#endif
sendLog(clients[j], msg.c_str(), strlen(msg.c_str()), 0);
}
}
void closeConnection()
{
for(int i = 0; i < (int)clients.size(); i++)
{
shutdown(clients[i], 2);
#ifdef _WIN32
closesocket(clients[i]);
#endif
#ifdef __linux__
close(clients[i]);
#endif
}
#ifdef _WIN32
closesocket(socketId);
WSACleanup();
#endif
#ifdef __linux__
close(socketId);
#endif
}
void freeNetwork()
{
closeConnection();
}`

to expand on Barmar's comment
TCP is a streaming protocol, not a message protocol. THe only guarantee is that you send n bytes, you will receive n bytes in the same order.
You might send 1 chunk of 100 bytes and receive 100 1 byte recvs, or you might receive 20 5 bytes recvs
You could send 100 1 byte chunks and receive 4 25 byte messages
You must deal with message boundaries yourself. Either have a sentinel value to mark start and end or prepend a length that is a fixed size itself (so you know you have read the whole length). Then loop on recv till you have received the whole message

Related

Producer/Consumer High performance UDP packet capture/sniffing in C++

I am struggling a UDP packet sniffing program which shall capture packets as efficient as wireshark. What I simply do is opening a UDP socket with highest thread priority to capture packets from 192.168.2.20 over port 5001.
After quite a few of trials (sending a couple of seconds of UDP transmission from another computer which has 192.168.2.20 interface on port 5001 using iperf), I come up with the solution of producer/consumer multithreaded program under c++. My objection is to printout the size and the identification number of received packet until the transmission ends (the program will run for weeks).
So, I use the producer buffer as a queue to capture received UDP packets until reaching a queue limit (i.e. 40000). After the limit is achieved, the producer copies its content into another queue buffer and clears its content to continue receiving UDP packets which consumer thread will utilizes so that no thread synchronization will be needed. However, my program does not work perfectly. Below is my code. How can I achieve my goal (printing out total number of received UDP packets and its identification numbers more efficiently)
#include <iostream>
#include <thread>
#include <array>
#include <vector>
#include <mutex>
#include <string>
#include <unistd.h>
#include <condition_variable>
#include <queue>
#include <algorithm>
#include <string.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <chrono>
#include <sys/time.h>
#include <ctime>
#include <numeric>
using namespace std;
const int BUFFER_SIZE = 2000;
#define ETH_DATA_LEN 1512
#define UDP 0x11
#define SRC_ADDR "192.168.2.20"
mutex m;
mutex m_print;
bool is_qq_empty = true;
bool is_transmission_continue = true;
bool is_producer_started = false;
struct ReceiveBufferArray {
uint8_t buf[ETH_DATA_LEN];
int id;
time_t time;
int index;
};
vector<int> packetSize;
vector<int> consume_buffer;
vector<int> loss_buffer;
vector<std::time_t> time_buffer;
std::queue<ReceiveBufferArray> qq;
std::queue<ReceiveBufferArray> qq_copy;
int gmSocket;
struct sockaddr_in gmClientAddr;
struct sockaddr_in gmServerAddr;
socklen_t gmClientLen = sizeof(gmServerAddr);
int openSocket(const std::string &IpAddress, int Port)
{
int ret;
struct timeval timeout;
int optval = 1;
gmSocket = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (gmSocket < 0)
{
std::cout << "cannot Open datagram socket!! Ip: " << IpAddress << " - Port " << std::to_string(Port) << std::endl;
return -1;
}
/* Bind our local address so that the client can send to us */
gmServerAddr.sin_family = AF_INET;
gmServerAddr.sin_addr.s_addr =INADDR_ANY;
gmServerAddr.sin_port = htons(Port);
timeout.tv_sec = 10;// timeout for 10seconds
timeout.tv_usec = 0;
setsockopt(gmSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
setsockopt(gmSocket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
setsockopt(gmSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
std::cout << "Socket has been opened. Ip: " << IpAddress << " - Port " << std::to_string(Port) << std::endl;
return 0;
}
void clear(std::queue<ReceiveBufferArray> &q)
{
std::queue<ReceiveBufferArray> empty;
std::swap(q,empty);
}
std::queue<ReceiveBufferArray> copy_queue(std::queue<ReceiveBufferArray> &q)
{
std::queue<ReceiveBufferArray>Q2 =q;
return Q2;
}
void consumer_thread()
{
struct sockaddr_in source_socket_address, dest_socket_address;
memset(&source_socket_address, 0, sizeof(source_socket_address));
memset(&dest_socket_address, 0, sizeof(dest_socket_address));
uint8_t ethernet_data[ETH_DATA_LEN];
int old_val = 99999;
bool start_copying_flag = false;
while (is_transmission_continue || qq_copy.empty())
{
if (!qq_copy.empty())
{
start_copying_flag = true;
// Record start time
m.lock();
std::copy(std::begin(qq_copy.front().buf),std::end(qq_copy.front().buf), std::begin(ethernet_data));
qq_copy.pop();
m.unlock();
struct iphdr *ip_packet = (struct iphdr *)ethernet_data;
if((ip_packet->saddr == inet_addr(SRC_ADDR)) && (ip_packet->protocol == UDP))
{
consume_buffer.push_back(ntohs(ip_packet->id));
std::cout << "id: " << std::to_string(ntohs(ip_packet->id))
<< ", Packet Number: " << std::to_string(consume_buffer.size())<<endl;
}
usleep(1);
}else if(qq_copy.empty() && start_copying_flag)
{
if(qq.size()>0)
{
m.lock();//##################################################3
qq_copy = copy_queue(qq);
clear(qq);
m.unlock();//##################################################3
}
}
}
}
void producer_thread()
{
int packet_size;
openSocket(SRC_ADDR,5001);
ReceiveBufferArray _rbuf;
int counter = 0;
while (is_transmission_continue)
{
packet_size = recvfrom(gmSocket , _rbuf.buf , ETH_DATA_LEN , 0 , NULL, NULL);
if (qq.size() < 40000)
{
counter++;
m.lock();
qq.push(_rbuf);
m.unlock();
std::cout <<"Packet Size : " << counter << endl;
}else {
std::cout << "PRODUCER EMPTY" << endl;
m.lock();//##################################################3
qq_copy = copy_queue(qq);
m.unlock();//##################################################3
clear(qq);
is_producer_started = true;
}
if((packet_size < 0) && is_producer_started){
is_transmission_continue =false;
}
}
std::cout << "PRODUCER DONE" << endl;
}
int main()
{
setpriority(PRIO_PROCESS, 0, -20);
thread cons(consumer_thread);
thread prod(producer_thread);
prod.join();
cons.join();
return 0;
}

Im unsure of why my http server is not reading in a filelocation C++

Im creating a http server in c++. I know that TCPServer.h works and that thing/text.txt exists but for some reason the code doesnt read the text file when I do 127.0.0.1. If you would like TCPServer.h to help help just ask I would be more than happy to send it but I just didnt see a reason to do it
#include "TCPServer.h"
#include <future>
#include <fstream>
#include <WS2tcpip.h>
#include <iostream>
#define MAX_BUF (4096)
#pragma comment (lib, "ws2_32.lib")
char * getLoc(char * c) {
char * ret = (char *)malloc(4096);
ZeroMemory(ret, 4096);
for(int i = 4; i < 4092; i++) {
if (*(c + i) == ' ') {
return ret;
}
else {
*(ret + i - 4) = *(c + i);
}
}
return ret;
}
void doStuff(SOCKET sock) {
char * recieved = (char *)malloc(4096);
recv(sock, recieved, 4096, 0);
char * loc = getLoc(recieved);
std::string fileLocation("thing");
fileLocation += loc;
std::ifstream fil;
fil.open(fileLocation);
char * contents = (char *)malloc(4096);
ZeroMemory(contents, 4096);
fil.read(contents, 4096);
fil.close();
std::cout << fileLocation;
std::string shoot("HTTP/1.1 200 OK\n");
shoot += contents;
std::cout << "\n\n\n" << shoot;
send(sock, shoot.c_str(), 4096, 0);
}
int main() {
TCPServ s;
s.createSock(80);
while (true) {
SOCKET sock = s.listenFor();
std::future <void> f = std::async(doStuff, sock);
}
}

Strange behaviour from C++ program with RF24 Radio Library and Interrupts on Raspi

I've been running a script on my Raspi while incrementally improving its performance, it was working fine until I started editing it this morning, and now cout << will not print to the console but interestingly enough - radio.printDetails does print, which uses printf. I think maybe the SD card is starting to die? Could this cause the issue?
Header:
#include <bcm2835.h>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <RF24/RF24.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
#include <time.h>
#define arrSize 50
//
// Hardware configuration
// Configure the appropriate pins for your connections
/****************** Raspberry Pi ***********************/
RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0);//, BCM2835_SPI_SPEED_4MHZ);
//RF24 radio(22,0); // CE GPIO, CSN SPI-BUS
int interruptPin = 23; // GPIO pin for interrupts
int i=0;
/**************************************************************/
// Radio pipe addresses for the 2 nodes to communicate.
//const uint8_t pipes[][6] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
const uint8_t pipes[][6] = {"1Node","2Node"};
volatile int accelArryNo = 0;
volatile int currentArryNo = 0;
uint8_t ack = 30;
int liveAccelArray[arrSize*3];
float liveCurrentArray[arrSize];
const int max_receivePayload_size = 32;
volatile int recvd = 0;
uint8_t receivePayload[max_receivePayload_size]; // +1 to allow room for a terminating NULL char
uint8_t receivePayloadBuff[max_receivePayload_size];
bool role_ping_out = 1, role_pong_back = 0;
bool role = 0;
//mysql pointers
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
main():
int main(){
char *server = "localhost";
char *user = "monitor";
char *password = "monitor"; /* set me first */
char *database = "data";
conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(conn, server,
user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
/* send SQL query */
if (mysql_query(conn, "show tables")) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_use_result(conn);
/* output table name */
// printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(res)) != NULL)
//printf("%s \n", row[0]);
mysql_free_result(res);
// Setup and configure rf radio
radio.begin();
radio.setAutoAck(1);
radio.enableDynamicPayloads();
radio.enableAckPayload();
radio.setRetries(0,15);
radio.setDataRate(RF24_1MBPS);
radio.printDetails();
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
radio.writeAckPayload(1, &ack, sizeof(ack));
if(radio.available()){
std::cout << "available";
uint8_t len;
len = radio.getDynamicPayloadSize();
radio.read(&receivePayload, len);
}
std::cout << "listening";
attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23
radio.startListening();
// forever loop
while(1){
if (recvd == 2){
//addLiveData();
recvd = 0;
} else if (recvd == 1) {
insertData();
recvd = 0;
}
}
}
Thanks

MQTT connect with activeMQ

I have written a client code for mqtt which is supposed to connect (just connect to server for now) to a active mq server. following is the code:
#include "stdafx.h"
#include<iostream>
#include<winsock2.h>
#include "mqtt.h"
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#include <stdlib.h>
#include <winsock2.h>
void mqtt_init(mqtt_broker_handle_t* broker, const char* clientid) {
// Connection options
broker->alive = 300; // 300 seconds = 5 minutes
broker->seq = 1; // Sequence for message identifiers
// Client options
memset(broker->clientid, 0, sizeof(broker->clientid));
memset(broker->username, 0, sizeof(broker->username));
memset(broker->password, 0, sizeof(broker->password));
if(clientid) {
strncpy_s(broker->clientid, clientid, sizeof(broker->clientid));
} else {
strcpy_s(broker->clientid, "emqtt");
}
// Will topic
broker->clean_session = 1;
}
void mqtt_init_auth(mqtt_broker_handle_t* broker, const char* username, const char* password)
{
if(username && username[0] != '\0')
strncpy_s(broker->username, username, sizeof(broker->username)-1);
if(password && password[0] != '\0')
strncpy_s(broker->password, password, sizeof(broker->password)-1);
}
using namespace std;
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char message[1000] , server_reply[2000];
int recv_size;
int packet_length;
uint16_t msg_id, msg_id_rcv;
mqtt_broker_handle_t broker;
mqtt_init(&broker, "localhost");
mqtt_init_auth(&broker, "cid", "campeador");
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) {
cout<<"Failed. Error Code : "<<WSAGetLastError();
return 1;
}
cout<<"Initialised.\n";
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
cout<<"Could not create socket : " << WSAGetLastError();
}
cout<<"Socket created.\n";
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 1993);
//Connect to remote server
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
mqtt_connect(&broker);
recv_size = recv(s, server_reply, 2000, 0);
server_reply[recv_size] = '\0';
while ( server_reply != "end"){
cout<<server_reply<<endl;
recv_size = recv(s, server_reply, 2000, 0);
server_reply[recv_size] = '\0';
}
closesocket(s);
WSACleanup();
return 0;
}
And also the following is the code for mqtt.h
#ifndef __LIBEMQTT_H__
#define __LIBEMQTT_H__
#endif
#include <stdint.h>
#include <string.h>
#ifndef MQTT_CONF_USERNAME_LENGTH
#define MQTT_CONF_USERNAME_LENGTH 13 // Recommended by MQTT Specification (12 + '\0')
#endif
#ifndef MQTT_CONF_PASSWORD_LENGTH
#define MQTT_CONF_PASSWORD_LENGTH 13 // Recommended by MQTT Specification (12 + '\0')
#endif
#define MQTT_MSG_CONNECT 1<<4
#define MQTT_MSG_CONNACK 2<<4
#define MQTT_MSG_PUBLISH 3<<4
#define MQTT_MSG_PUBACK 4<<4
#define MQTT_MSG_PUBREC 5<<4
#define MQTT_MSG_PUBREL 6<<4
#define MQTT_MSG_PUBCOMP 7<<4
#define MQTT_MSG_SUBSCRIBE 8<<4
#define MQTT_MSG_SUBACK 9<<4
#define MQTT_MSG_UNSUBSCRIBE 10<<4
#define MQTT_MSG_UNSUBACK 11<<4
#define MQTT_MSG_PINGREQ 12<<4
#define MQTT_MSG_PINGRESP 13<<4
#define MQTT_MSG_DISCONNECT 14<<4
#define MQTT_DUP_FLAG 1<<3
#define MQTT_QOS0_FLAG 0<<1
#define MQTT_QOS1_FLAG 1<<1
#define MQTT_QOS2_FLAG 2<<1
#define MQTT_RETAIN_FLAG 1
#define MQTT_CLEAN_SESSION 1<<1
#define MQTT_WILL_FLAG 1<<2
#define MQTT_WILL_RETAIN 1<<5
#define MQTT_USERNAME_FLAG 1<<7
#define MQTT_PASSWORD_FLAG 1<<6
typedef struct {
void* socket_info;
int (*send)(void* socket_info, const void* buf, unsigned int count);
// Connection info
char clientid[50];
// Auth fields
char username[MQTT_CONF_USERNAME_LENGTH];
char password[MQTT_CONF_PASSWORD_LENGTH];
// Will topic
uint8_t will_retain;
uint8_t will_qos;
uint8_t clean_session;
// Management fields
uint16_t seq;
uint16_t alive;
} mqtt_broker_handle_t;
int mqtt_connect(mqtt_broker_handle_t* broker)
{
uint8_t flags = 0x00;
uint16_t clientidlen = strlen(broker->clientid);
uint16_t usernamelen = strlen(broker->username);
uint16_t passwordlen = strlen(broker->password);
uint16_t payload_len = clientidlen + 2;
// Preparing the flags
if(usernamelen) {
payload_len += usernamelen + 2;
flags |= MQTT_USERNAME_FLAG;
}
if(passwordlen) {
payload_len += passwordlen + 2;
flags |= MQTT_PASSWORD_FLAG;
}
if(broker->clean_session) {
flags |= MQTT_CLEAN_SESSION;
}
// Variable header
uint8_t var_header[] = {
0x00,0x06,0x4d,0x51,0x49,0x73,0x64,0x70, // Protocol name: MQTT
0x03, // Protocol version
flags, // Connect flags
broker->alive>>8, broker->alive&0xFF, // Keep alive
};
// Fixed header
uint8_t fixedHeaderSize = 2; // Default size = one byte Message Type + one byte Remaining Length
uint8_t remainLen = sizeof(var_header)+payload_len;
if (remainLen > 127) {
fixedHeaderSize++; // add an additional byte for Remaining Length
}
uint8_t fixed_header[2];
// Message Type
fixed_header[0] = MQTT_MSG_CONNECT;
// Remaining Length
if (remainLen <= 127) {
fixed_header[1] = remainLen;
} else {
// first byte is remainder (mod) of 128, then set the MSB to indicate more bytes
fixed_header[1] = remainLen % 128;
fixed_header[1] = fixed_header[1] | 0x80;
// second byte is number of 128s
fixed_header[2] = remainLen / 128;
}
uint16_t offset = 0;
uint8_t packet[sizeof(fixed_header)+sizeof(var_header)+ sizeof(payload_len)];
memset(packet, 0, sizeof(packet));
memcpy(packet, fixed_header, sizeof(fixed_header));
offset += sizeof(fixed_header);
memcpy(packet+offset, var_header, sizeof(var_header));
offset += sizeof(var_header);
// Client ID - UTF encoded
packet[offset++] = clientidlen>>8;
packet[offset++] = clientidlen&0xFF;
memcpy(packet+offset, broker->clientid, clientidlen);
offset += clientidlen;
if(usernamelen) {
// Username - UTF encoded
packet[offset++] = usernamelen>>8;
packet[offset++] = usernamelen&0xFF;
memcpy(packet+offset, broker->username, usernamelen);
offset += usernamelen;
}
if(passwordlen) {
// Password - UTF encoded
packet[offset++] = passwordlen>>8;
packet[offset++] = passwordlen&0xFF;
memcpy(packet+offset, broker->password, passwordlen);
offset += passwordlen;
}
return 1;
}
When I debug the code there are no errors however when I run the code I get error stating that "the stack around the variable 'packet' is corrupt". I am very new to socket programming and mqtt in general so any help would be great.
What you've shown is derived from libemqtt (which is GPL licensed by the way, don't forget that :), have you tried starting from the examples that they provide?
libemqtt isn't actively developed and has a notice saying "DO NOT USE". Unless you're particularly interested in solving the problem of using MQTT for yourself, I'd suggest you look at something different, like the Paho or mosquitto client libraries.

Using select without listen()ing, possible?

I am building a client that:
Should be able to recieve information from both the server and the standart input
Should be able to recieve information from the server without asking, for example when another client sends a message.
To do so I tried using select to monitor both possible inputs.
What happens is that when a keyboard input is monitored I send a message to the client and I expect one back, so there's no problem. But when the server sends an unexpected message nothing happens, and I don't know why. Is using select() the proper way to do so? Is it even possible to use select() without listen()ing?
Here's my code (compileable):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cstring>
#include <arpa/inet.h>
#include <iostream>
#include <fstream>
#define MAX_CLIENT_NAME 30
#define MAX_TWIT_SIZE 140
#define NUM_OF_ARG 4
#define ERROR -1
#define GREAT_SUCCESS 0
#define OK "OK"
#define EXIT "EXIT"
using std::string;
using std::cerr;
using std::endl;
using std::cout;
string clientName;
int srverfd, numbytes, status, maxSock ;
fd_set inputFdSet; /* Socket file descriptors we want to wake
up for, using select() */
int establishConnection(char * serverAddress,char * port){
if ((srverfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
return ERROR;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
inet_aton(serverAddress, &server.sin_addr);
server.sin_port = htons(atoi(port));
memset(&(server.sin_zero), '\0', 8);
if (connect(srverfd,(const struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("connect");
close(srverfd);
return ERROR;
}
maxSock = srverfd;
return GREAT_SUCCESS;
}
const char * getUserTweet(){
string temp;
getline(std::cin,temp);
return temp.c_str();
}
void sendMessage(string message){
if ((numbytes = send(srverfd, message.c_str(), message.length(), 0)) == -1) {
perror("sendMessage");
close(srverfd);
}
cout<<"Message sent: "<< message << endl;
return;
}
const char * getMessage(){
char buf[MAX_TWIT_SIZE];
memset(buf,'\0',MAX_TWIT_SIZE);
if ((numbytes = recv(srverfd, buf, 140, 0)) == -1) {
perror("getMessage");
close(srverfd);
}
string temp = buf;
return temp.c_str();
}
void build_select_list() {
FD_ZERO(&inputFdSet);
FD_SET(srverfd,&inputFdSet);
FD_SET(STDIN_FILENO,&inputFdSet);
if (STDIN_FILENO > maxSock)
maxSock = STDIN_FILENO;
return;
}
void readSocket(fd_set tempfd) {
const char * tweet, * inMessage;
if (FD_ISSET(srverfd,&tempfd)) {
inMessage = getMessage();
cout << inMessage << endl;
}
if (FD_ISSET(STDIN_FILENO,&tempfd)) {
tweet = getUserTweet();
sendMessage(tweet);
inMessage = getMessage();
if (strcmp(inMessage,OK) != 0) {
cout << inMessage << endl;
}
if (strcmp(inMessage,EXIT) == 0) {
return;
}
}
return;
}
int main (int argc, char *argv[] ){
int value;
bool clientON = false;
if(establishConnection(argv[2],argv[3])){
cerr << "usage: failed to make connection" << endl << "exiting..." << endl;
exit(EXIT_FAILURE);
}
cout << "Connected successfully" << endl;
sendMessage("CONNECT "+clientName); //Connect
if(strcmp(getMessage(),OK) == 0){
clientON = true;
}
while(clientON){
build_select_list();
value = select(maxSock, &inputFdSet, NULL, NULL, NULL);
if (value < 0) {
perror("select");
exit(EXIT_FAILURE);
}
if (value == 0) {
continue;
}
else {
readSocket(inputFdSet);
}
}
sendMessage("DISCONNECT");
if(strcmp(getMessage(),OK) == 0){
// do nothing
}
close(srverfd);
return 0;
}
Your select call is invalid. The first parameter must be the highest file descriptor in any of the sets, plus one.
As you have it, an event on srverfd will not "wake up" the select call (unless STDIN_FILENO was somehow less than srverfd, in which case stdin events wouldn't unlock select - but that won't happen in practice).
There are quite a few other problems with your code. (It doesn't really look like C++.)
getUserTweet is unreliable (undefined behavior - temp is destroyed as soon as the function returns, so the char* you return has disappeared by the time its caller will try to use it). Same for getMessage. To remedy that, use std::string everywhere, and only extract the char* when you call into C library functions).
readSocket needlessly copies the FD set (can be expensive).
You should really get rid of all those globals - build one or two classes to encapsulate that state and the networking functions, or something like that.