int mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
if(broker == 0) {
printf("Connection failed, Please check the IP and port of broker\n");
return 0;
}
else {
printf("Connection established successfully\n");
}
return 1;
}
int publish_mqtt()
{
char msg[128] = "Test 2";
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
{
printf("publish failed\n");
}
else {
printf("Sent messages\n");
}
return(0);
}
I am getting error while building using scons as
master.c: In function 'publish_mqtt':
master.c:39:17: error: 'broker' undeclared (first use in this function)
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
^
master.c:39:17: note: each undeclared identifier is reported only once for each function it appears in
scons: *** [master.o] Error 1
scons: building terminated because of errors.
How to exchange the value of broker between two functions?. Is there any other way to implement this?
How to exchange the value of broker between two functions?. Is there any other way to implement this?.
Change the signatures of both functions.
Change the first function to return broker.
Change the second function to expect broker as an argument.
mqtt_broker_handle_t* mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
if(broker == 0)
{
printf("Connection failed, Please check the IP and port of broker\n");
return NULL;
}
else
{
printf("Connection established successfully\n");
return broker;
}
}
int publish_mqtt(mqtt_broker_handle_t* broker)
{
char msg[128] = "Test 2";
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
{
printf("publish failed\n");
}
else
{
printf("Sent messages\n");
}
return(0);
}
Change the calling function.
mqtt_broker_handle_t* broker = mqtt_connection();
publish_mqtt(broker);
The problem lies in the fact broker is not available in the publish_mqtt function due to variable scoping.
Ie: Once the end brace of mqtt_connection is hit, broker no longer exists.
int mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
...
}
If you wish to use it within publish_mqtt you need to shift the scope of the variable to be one that covers both functions. Ie:
mqtt_broker_handle_t *broker = NULL;
int mqtt_connection()
{
broker = mqtt_connect(client_name, ip_addr, port);
...
}
int publish_mqtt()
{
...
}
Related
What should I modify in the below codes in order to use only one message queue for one server and
multiple clients. I'm pretty sure I need to assign different values to msgid and then use that to fetch the messages from the message queue but not completely sure if I'm right and how to implement it. I would be grateful for any help.
Code1:
struct my_msg_st {
long int my_msg_type;
char some_text[BUFSIZ];
};
int main() {
int running = 1;
int msgid;
struct my_msg_st some_data;
long int msg_to_receive = 0
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1) {
fprintf(stderr, “msgget failed with error: %d\n”, errno);
exit(EXIT_FAILURE);
}
while(running) {
if (msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, 0) == -1) {
fprintf(stderr, “msgrcv failed with error: %d\n”, errno);
exit(EXIT_FAILURE);
}
printf(“You wrote: %s”, some_data.some_text);
if (strncmp(some_data.some_text, “end”, 3) == 0) {
running = 0;
}
}
if (msgctl(msgid, IPC_RMID, 0) == -1) {
fprintf(stderr, “msgctl(IPC_RMID) failed\n”);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
Code 2:
#define MAX_TEXT 512
struct my_msg_st {
long int my_msg_type; char some_text[MAX_TEXT];
};
int main() {
int running = 1;
struct my_msg_st some_data; int msgid;
char buffer[BUFSIZ];
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1) {
fprintf(stderr, “msgget failed with error: %d\n”, errno);
exit(EXIT_FAILURE);
}
while(running) {
printf(“Enter some text: “);
fgets(buffer, BUFSIZ, stdin);
some_data.my_msg_type = 1;
strcpy(some_data.some_text, buffer);
if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) {
fprintf(stderr, “msgsnd failed\n”);
exit(EXIT_FAILURE);
}
if (strncmp(buffer, “end”, 3) == 0) {
running = 0;
}
}
exit(EXIT_SUCCESS);
}
I suggest that you create a single queue and each message that you push to the queue should have a different value for my_msg_type instead of hard coding it to 1 as you have done. This is the mapping between the client and server. Each client can be numbered from 1 till n.
some_data.my_msg_type = client_id;
Once this is done in each client you can call msgrcv with its corresponding client ID. This can be done by using the client ID as the 4th argument in msgrcv.
msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, client_id)
This way you have a single server generating data for multiple clients.
Hope that helps!
I have a raspberry pi that connects to a TCP server and sends some data every couple of seconds, I want to be able to handle all kind of failures and disconnects, so at the moment I am trying a test where I disconnect the Huawei USB dongle that I am connecting through.
I have a thread that runs in the background and check the connection periodically. The code does not reconnect when I remove the USB dongle and plug it back in sometime later, I need help on how to make this more robust. At the moment on the server side I see that after I plug back in the USB dongle I see the client connect but immediately disconnect from it.
The thread is called KeepSocketOpen and inside here I call a ping function to 8.8.8.8 to see if the connection is still active and here is my code, I'm kind of new to socket programming so excuse the mess:
int ping(char *ipaddr)
{
char *command = NULL;
FILE *fp;
int x, match=0;
char* result = NULL;
size_t len = 0;
asprintf (&command, "%s %s -p 50 -r 3", "fping", ipaddr);
//printf ("%s %s -q 2>&1", "fping", ipaddr);
fp = popen(command, "r");
if (fp == NULL) {
fprintf(stderr, "Failed to execute fping command\n");
free(command);
return -1;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout);
//printf("%s",result);
}
for(x=0;x<len;x++)
{
if(x>5 && result[x]=='e'&& result[x-1]=='v'&& result[x-2]=='i'&& result[x-3]=='l'&& result[x-4]=='a')
{
match=1;
break;
}
}
if(match==0)
sleep(5);
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
free(command);
//printf("%s\r\n",result);
if(match==0)
return -1;
else
return 1;
}
void* KeepSocketOpen(void *arg)
{
pthread_t id= pthread_self();
char tcprxbuff[1024];
int numbytes, status=0,attempts,reuse=1;
struct timeval timeout={0};
timeout.tv_sec=10;
timeout.tv_usec=0;
printf("in sock thread\r\n");
while(1)
{
if(is_socket_connected==0)
{
sock=socket(AF_INET,SOCK_STREAM,0);
addr.sin_family = AF_INET;
addr.sin_port = htons(34879);
addr.sin_addr.s_addr=inet_addr("X.X.X.X");
attempts=0;
setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
setsockopt(sock, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));
status=connect(sock, (struct sockaddr *) &addr,sizeof (addr));
// wait for 5s and see if the socket has connected
do
{
delay(5);
}
while(errno && attempts++<1000);
if (attempts >=1000 || errno) // this is the fail case
{
printf("socket not connected %s\r\n",strerror(errno));
is_socket_connected=0;
close(sock);
//shutdown(sock,SHUT_RDWR);
sleep(30);
}
else
{
// fcntl(sock, F_SETFL, O_NONBLOCK);
printf("socket reconnected %d,%s\r\n",attempts,strerror(errno));
is_socket_connected=1;
write(sock, "HI FROM RASPI", strlen("HI FROM RASPI"));
}
}
else
{
numbytes=read(sock,tcprxbuff,sizeof(tcprxbuff));
if(numbytes==0)// if this is zero, socket was closed by server
{
is_socket_connected=0;
while(close(sock)==-1);
}
else
{
printf("socket connected:%d\r\n",numbytes);
status = ping("8.8.8.8");
if (status!=-1) {
printf("socket still connected:%d\r\n",status);
is_socket_connected=1;
} else {
printf("socket disconnected:%d\r\n",status);
is_socket_connected=0;
//shutdown(sock,SHUT_RDWR);
while(close(sock)==-1);
}
}
sleep(30);
}
}
}
I have a little problem about paho mqtt library.
I register a callback function MQTTClient_messageArrived and MQTTClient_connectionLost.
And I call MQTTClient_subscribe() or MQTTClient_unsubscribe() in this callback function. After running this callback function. I got a error code (-3) from MQTTClient_connectionLost. Furthermore, I print the cause is NULL.
Is any possible problem to my problem? Thanks
Here are my initialize function and callback function:
void mqtt_initialize(void){
int rc;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
if(MQTTClient_create(&g_MQTT_client, BROKER_ADDR, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL) < 0){
g_mqtt_exist = MQTT_INSTANCE_NOT_EXIST;
} else {
g_mqtt_exist = MQTT_INSTANCE_EXIST;
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(g_MQTT_client, NULL, mqtt_connlost_cb, mqtt_arrived_cb, mqtt_delivered_cb);
if ((rc = MQTTClient_connect(g_MQTT_client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
MAIN_PRINT_DEBUG(0, "Failed to connect MQTT broker, return code %d\n", rc);
mqtt_free();
}
/* set subscribe control topic */
MQTTClient_subscribe(g_MQTT_client, "topic_1", MQTT_QOS);
}
int mqtt_arrived_cb(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
int ret = 0;
printf("topic: %s\n", topicName);
if(!strcmp(topicName, "topic_1")){
printf("topic_1\n");
ret = MQTTClient_subscribe(g_MQTT_client, "topic_2", 0);
if (ret < 0){
printf("mqtt operation fail\n");
}
}
return 1;
}
void mqtt_connlost_cb(void *context, char *cause)
{
MAIN_PRINT_DEBUG(0, "\n MQTT Connection lost\n");
MAIN_PRINT_DEBUG(0," cause: %s\n", cause);
}
Did you try connecting any other client to same broker with same client id? That could be a possible case if you are getting connection lost. Also if your callback throws exception, it will cause connection lost, however in this case paho will reconnect.
I saw this question but it doesn't seem to apply.
Heres my function which does most the heavy lifting in the client code:
void
database_1(char *host, char *action, char *message)
{
printf("Action: %s\n", action);
printf("Message: %s\n", message);
CLIENT *clnt;
rpc_args *result_1;
//struct rpc_args action_1_arg;
//rpc arguments struct to pass to server
struct rpc_args *args = malloc(sizeof(struct rpc_args));
char *id = generate_id();
if (strcmp(action, "GET") == 0) {
printf("Client: GET request\n");
strcpy(args->action, action);
strcpy(args->id, id);
} else if(strcmp(action, "PUT") == 0) {
printf("Client: PUT request\n");
strcpy(args->action, action);
strcpy(args->id, id);
strcpy(args->message.content, message);
}
#ifndef DEBUG
clnt = clnt_create (host, DATABASE, ASSIGNMENT_7, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
#endif /* DEBUG */
result_1 = action_1(args, clnt);
if (result_1 == (rpc_args *) NULL) {
clnt_perror (clnt, "call failed");
}
free(args);
#ifndef DEBUG
clnt_destroy (clnt);
#endif /* DEBUG */
}
Here's my output:
./database_client eecslinab3.case.edu GET
running client, main
Action: GET
Message: (null)
hostname is eecslinab3
The process id is 24697
The unique id is eecslinab324697
Client: GET request
call failed: RPC: Can't encode arguments
Database.x
struct message {
char content[2000];
};
struct rpc_args {
char action[20];
char id[1024];
struct message message;
};
program DATABASE {
version ASSIGNMENT_7 {
rpc_args ACTION(struct rpc_args) = 1;
} = 1;
} = 0x20fff100;
A friend helped me solve the problem but didn't give me much details about why or how the fix works. Basically I reduced the char array sizes in my struct and it worked. Has something to do with the limit of data you can send over UDP.
struct rpc_args {
char action[20];
char id[80];
char message[80];
};
program DATABASE {
version ASSIGNMENT_7 {
rpc_args ACTION(struct rpc_args) = 1;
} = 1;
} = 0x20fff100;
I am new to this website so I do appologize in advance if this question has been answered before though I have searched it before opening it to everyone here.
I am using socket programming in one of my C program. It has server and client modules where sever and client can communicate in both directions. Program is working fine as I am able to send files and messages in both directions.
My server program is using port 3873 and I have confirmed this with netstat -anp | grep 3873
I have observed one weird behaviour with socket especially when I try to connect socket using browser such as http://localhost:3873 or telnet localhost 3873. It immediately closed socket and subsequent 'netstat -anp | grep 3873' output confirms that localhost is no longer listening on the port 3873.
I would really appreciate if someone can shed light on this behavior. Is it expected behavior?
Here is relevant section from the server code: Main program initiate a dedicated thread and calls startFileServerMT, which subsequent calls handleClient to service each client connected to server on the socket
int handleClient(void *ptr){
DEBUG("Inside the %s %s() \n",__FILE__,__func__);
int connectSOCKET;
connectSOCKET = (int ) ptr;
char recvBUFF[4096],sendBUFF[4096];
char *filename;
FILE * recvFILE;
char *header[4096];
while(1){
if( recv(connectSOCKET, recvBUFF, sizeof(recvBUFF), 0) > 0){
if(!strncmp(recvBUFF,"FBEGIN",6)) {
recvBUFF[strlen(recvBUFF) - 2] = 0;
parseArgs(header,recvBUFF);
filename = (char*) strngDup(header[1]);
DEBUG(" About to receive file: %s\n", filename);
}
char *rfile = ALLOC(sizeof(char) * (strlen(This.uploadDIR) + strlen(filename) + 35));
strcpy(rfile,This.uploadDIR);
if (strngLastChar(rfile) == '/'){
strcat(rfile,filename);
}else{
strcat(rfile,"/");
strcat(rfile,filename);
}
DEBUG(" Absolute file is : %s\n", rfile);
recvBUFF[0] = 0;
if ((recvFILE = fopen (rfile,"w" )) == NULL){
LogError("Server could not create file %s on the shared location %s.\n",filename,This.uploadDIR);
}else{
bzero(recvBUFF,4096);
int fr_block_sz, write_sz;
while((fr_block_sz = recv(connectSOCKET, recvBUFF, 512, 0)) > 0 ){
write_sz = fwrite (recvBUFF , sizeof(recvBUFF[0]) , fr_block_sz , recvFILE );
DEBUG(" Received buffer is : %s\n", recvBUFF);
if(write_sz < fr_block_sz){
LogError("Failed writing file %s on the Server shared location.\n",filename);
break;
}
bzero(recvBUFF,4096);
recvBUFF[0] = 0;
if(write_sz == 0 || fr_block_sz != 512 ){
break;
}
}
if(fr_block_sz < 0){
if(errno == EAGAIN){
LogError("Server collection file %s receive timed out.\n",filename);
}else{
LogError("Failed file %s transfer due to error %d\n",filename,errno);
fclose(recvFILE);
FREE(rfile);
// Start - Following code send failed status to client
sprintf(sendBUFF,"FSTATUS:FAILED\r\n");
if (send(connectSOCKET, sendBUFF, sizeof(sendBUFF), 0) >= 0){
DEBUG("File transfer status for file %s sent\n",filename);
}else{
DEBUG("Failed sending transfer status for file %s\n",filename);
return FALSE;
}
// End
close(connectSOCKET);
return FALSE;
}
}
DEBUG("File %s received on OM Server successfully.\n",filename);
// Start - Following code send failed status to client
sprintf(sendBUFF,"FSTATUS:SUCCESS\r\n");
if (send(connectSOCKET, sendBUFF, sizeof(sendBUFF), 0) >= 0){
DEBUG("File transfer status for file %s sent\n",filename);
}else{
DEBUG("Failed sending transfer status for file %s\n",filename);
return FALSE;
}
// End
fclose(recvFILE);
updateTargets(rfile);
FREE(rfile);
close(connectSOCKET);
break;
}
}
else {
LogInfo("Client dropped connection\n");
}
/** End*/
return TRUE;
}
}
int startFileServerMT(){
DEBUG("Inside %s %s() \n",__FILE__,__func__);
int listenSOCKET, connectSOCKET[512],thread_status;
int socketINDEX = 0;
pthread_t clientFileThread[512];
socklen_t clientADDRESSLENGTH[512];
struct sockaddr_in clientADDRESS[512], serverADDRESS;
if((listenSOCKET = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
LogAbortError("File server could not create socket.\n");
close(listenSOCKET);
return FALSE;
}
serverADDRESS.sin_family = AF_INET;
serverADDRESS.sin_addr.s_addr = htonl(INADDR_ANY);
serverADDRESS.sin_port = htons(This.serverport);
if (bind(listenSOCKET, (struct sockaddr *) &serverADDRESS, sizeof(serverADDRESS)) < 0) {
LogAbortError("File server could not bind socket and will stop server now.\n");
close(listenSOCKET);
This.stopped = TRUE;
return FALSE;
}
if(listen(listenSOCKET, 5) == -1){
LogAbortError("Server failed to listen on port %d and will stop server now.\n",This.serverport);
close(listenSOCKET);
This.stopped = TRUE;
return FALSE;
}else{
LogInfo("Server listening on port %d successfully.\n",This.serverport);
}
clientADDRESSLENGTH[socketINDEX] = sizeof(clientADDRESS[socketINDEX]);
while(TRUE){
// DEBUG(" Inside the file server main loop index[%d].\n",socketINDEX);
connectSOCKET[socketINDEX] = accept(listenSOCKET, (struct sockaddr *) &clientADDRESS[socketINDEX], &clientADDRESSLENGTH[socketINDEX]);
if(connectSOCKET[socketINDEX] < 0){
LogError("Server could not accept connection.\n");
close(listenSOCKET);
return FALSE;
}else
DEBUG(" Another client connected to server socket.\n");
ThreadCreateDetached( &clientFileThread[socketINDEX], handleClient, connectSOCKET[socketINDEX]);
if(socketINDEX=512) {
socketINDEX = 0;
} else {
socketINDEX++;
}
if (This.stopped == TRUE){
close(listenSOCKET);
return TRUE;
}
/** End*/
// return TRUE;
}
close(listenSOCKET);
return TRUE;
}
This is your problem - or at least a part of your problem. It's not only an off-by-one error (connectSOCKET accepts indices from 0-511 inclusive so if you're at 512, you've already written past the end of the connectSOCKET array) but you do an assignment instead of a comparison:
if(socketINDEX=512) { // Error: you are *setting* socketINDEX to 512,
// then immediately *resetting* it back to 0. So
// every new connection overrides the existing
// socket.
socketINDEX = 0;
} else {
socketINDEX++;
}
As a sidenote, you really ought to refactor your code and try to clean it up.