I'm currently using this as a learning example:
https://os.mbed.com/teams/mqtt/code/MQTTPacket/file/aedcaf7984d5/samples/simple-publish.txt/
However, some of the code is specific to whatever embedded system the example is using.
What I got so far is:
#include "hw_util.h"
#include "MQTTPacket.h"
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
int main (void) {
int i;
float temperatura;
unsigned char buffer[50];
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
int rc = 0;
char buf[200];
int buflen = sizeof(buf);
MQTTString topicString = MQTTString_initializer;
char* payload = "I'm Alive";
int payloadlen = strlen(payload);
int len = 0;
data.clientID.cstring = "Testing";
data.keepAliveInterval = 20;
data.cleansession=1;
data.MQTTVersion=3;
len = MQTTSerialize_connect(buf,buflen,&data);
topicString.cstring="SampleTopic";
len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, payload, payloadlen);
printf("Hello world");
rc = 0;
while(1)
{
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
}
}
I downloaded HiveMQ, which is a Broker and it's running:
2018-03-05 19:28:08,195 INFO - Starting TCP listener on address 0.0.0.0 and port 1883
Now what I want to do, is send something like "Hello World" to this Broker or to Putty or something that would display the entire MQTT payload. How does C handle this? The documentation helped me understand what's going on but didnt really help me write C code, since I am still very new to it.
This took a while but I figured it out. There are still plenty of kinks to work out, but at least it sends an MQTT(Wireshark approved) packet to localhost.
Create an MQTT packet using this library: https://os.mbed.com/teams/mqtt/code/MQTTPacket/
Using this code:
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
char buf[200];
MQTTString topicString = MQTTString_initializer;
data.clientID.cstring = "TESTIRAM";
data.keepAliveInterval = 20;
data.cleansession=1;
data.MQTTVersion=3;
len = MQTTSerialize_connect(buf,buflen,&data);
topicString.cstring="ka";
len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0,
topicString, payload, payloadlen);
Set up a socket:
This code worked for me, but its LINUX SPECIFIC!
#include "hw_util.h"
#include "MQTTPacket.h"
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
char buf[200];
int mysock=0;
char *host = "127.0.0.1";
int port = 1883;
mysock = socket(AF_INET, SOCK_STREAM, 0);
AF_INET specifies IPv4 and SOCK_STREAM specifies TCP.
Connect to socket
Use this:
struct sockaddr_in cliaddr;
int rc = 0;
//initialize the host address
memset(&cliaddr, 0, sizeof(cliaddr));
//specify IPv4 protocol
/*following includes are necessary for this:#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>*/
cliaddr.sin_family = AF_INET;
//intialize the IP address of the host as "127.0.0.1"
cliaddr.sin_addr.s_addr = inet_addr(host);
//initialize the port, 1883
cliaddr.sin_port = htons(port);
//client has no bind
//socket()>connect()->send()<->recv()->close
int statusConn = connect(mysock,(const struct sockaddr*)&cliaddr,sizeof(cliaddr));
if(statusConn=0){
printf("Success!");
}
if(statusConn=-1){
printf("Connect unsuccessful!\n");
Send over socket!
This should work:
while(1)
{
printf("Sending to hostname %s port %d\n", host, port);
//infinite loop, sending packets to the specified ASOCKET
//after sending sleep for 10 seconds
//sleep uses unistd.h
printf("Sent packets: ");
int countSend = send(mysock ,buf,buflen,0);
printf("%d",countSend);
printf("\n");
sleep(10);
}
Some of the imports might be useless and some might be Linux specific. I'm moving onto AT commands so most of the issues in this code won't transfer to the new codebase.
Related
I wrote a server program and a client program that communicate with sockets on linux ubuntu. The client program outputs Received: 艎��
This my server code:
/*** tcp_server.c ***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main() {
int sock_fd, new_fd, bytes;
struct sockaddr_in seraddr, cliaddr;
char data[1024];
socklen_t cli_addr_size;
cli_addr_size = sizeof(cliaddr);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY : It received Network Interface that connected server defined interface, htonl :
seraddr.sin_port = htons(5050);
bind(sock_fd, (struct sockaddr *)&seraddr, sizeof(seraddr));
listen(sock_fd, 10);
while (1) {
new_fd = accept(sock_fd, (struct sockaddr *)&cliaddr, &cli_addr_size);
bytes = recv(new_fd, data, 1024, 0);
send(new_fd, data, bytes, 0);
close(new_fd);
}
close(sock_fd);
}
My client code is:
/*** tcp_client.c ***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main(int argc, char *argv[]) {
int sock_fd, bytes;
struct sockaddr_in ser_addr;
char *snddata, rcvdata[1024];
snddata = argv[2];
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
memset(&ser_addr, 0,sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = inet_addr(argv[1]); // INADDR_ANY : It received Network Interface that connected server defined interface, htonl :
ser_addr.sin_port = htons(5050);
connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
send(sock_fd, snddata, strlen(snddata), 0);
printf("Received: ");
bytes = recv(sock_fd, rcvdata, 1024, 0);
rcvdata[bytes] = '\0';
printf("%s\n", rcvdata);
close(sock_fd);
}
First I got an error for argument 3 of accept, then I changed
new_fd = accept(sock_fd, (struct sockaddr *)&cliaddr, sizeof(cliaddr);
But It still produces this strange word.
Try to change your send() and receive() functions so that you have full control over how much and which byte you send from the buffer (data[1024]) like in this thread : C socket: recv and send all data and also see Beej's Guide to Network Programming (http://beej.us/guide/bgnet/)
Also make sure that you initialize your data buffers:
data[1024] = "";
rcvdata[1024] = "";
or
data[1024];
data[0] = '\0';
rcvdata[1024];
rcvdata[0] = '\0';
, background is in this thread : Why I am getting this unusually symbols by printing char string
I have the following code for client and server
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int socket_fd;
struct sockaddr_in dest;
struct hostent *hostptr;
struct { char head; u_long body; char tail; } msgbuf;
socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
bzero((char *) &dest, sizeof(dest)); /* They say you must do this */
hostptr = gethostbyname(argv[1]);
dest.sin_family = (short) AF_INET;
bcopy(hostptr->h_addr, (char *)&dest.sin_addr,hostptr->h_length);
dest.sin_port = htons((u_short)0x3333);
msgbuf.head = '<';
msgbuf.body = htonl(getpid()); /* IMPORTANT! */
msgbuf.tail = '>';
sendto(socket_fd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr *)&dest,
sizeof(dest));
return 0;
}
server:
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int socket_fd, cc, fsize;
struct sockaddr_in s_in, from;
struct { char head; u_long body; char tail;} msg;
socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
bzero((char *) &s_in, sizeof(s_in)); /* They say you must do this */
s_in.sin_family = (short)AF_INET;
s_in.sin_addr.s_addr = htonl(INADDR_ANY); /* WILDCARD */
s_in.sin_port = htons((u_short)0x3333);
printsin( &s_in, "RECV_UDP", "Local socket is:");
fflush(stdout);
bind(socket_fd, (struct sockaddr *)&s_in, sizeof(s_in));
for(;;) {
fsize = sizeof(from);
cc = recvfrom(socket_fd,&msg,sizeof(msg),0,(struct sockaddr *)&from,&fsize);
//printsin( &from, "recv_udp: ", "Packet from:");
printf("Got data ::%c%ld%c\n",msg.head,(long) ntohl(msg.body),msg.tail);
fflush(stdout);
}
return 0;
}
I'm looking for a way to change this code so that:
1.The client will send my name to the server and then will receive the server response.
2.On the server side, the server will receive the client name (instead of the current msg structure) and will send back its name.
I'm assuming I should just put my name in the msgbuf.body like this
msgbuf.head = '<';
msgbuf.body = 'liana';
msgbuf.tail = '>';
and delete the
msgbuf.body = htonl(getpid()); line.
or maybe make a new string for my name like this string name="liana";
and put it in the msgbuf.body like this msgbuf.body=name;(???)
is this the right deriction?
for reciving the response of the server I assume it is the same way as it was done for the server
should I add to client something like this?
int socket_fd, cc, fsize; // the socket that we receive to
struct sockaddr_in s_in, from; // decleration of the server and sending
(to the server) struct
fflush(stdout);//to ensure that whatever you just wrote to a file/the console is indeed written out on disk/the console.
bind(socket_fd, (struct sockaddr *)&s_in, sizeof(s_in));// conecting
between
the socket and all the details we entered
for(;;) {//infinite loop
fsize = sizeof(from);//set the size of the socket we resive to
cc = recvfrom(socket_fd,&msg,sizeof(msg),0,(struct sockaddr
*)&from,&fsize);//recive massage using UDP protocol
printf("Got data ::%c%ld%c\n",msg.head,(long) ntohl(msg.body),msg.tail);
//print the whole massage
fflush(stdout);//to ensure that whatever you just wrote to a file/the
console is indeed written out on disk/the console.
}
and just leave it like this without changing anything?
**how can I make the server receive the my name (instead of the current msg
structure)and send it back?
should I send it back using the
sendto(socket_fd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr *)&dest,
sizeof(dest));
line?
**if I cant use the structure anymore how should i change this line?****
any help whould be appreciated,I'm kind of new to C and never worked with the client/server model
I have two programs udp sender and consumer on localhost. Sender generates four byte int messages at top speed, but the consumer does not get all of them. Consumer last line on stdout is
1484444 1999999
Wireshark intercepts all packages and slowly processes them all. How can I get the same behavior in a C program?
// sender.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int main()
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in dest;
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(40500);
inet_aton("127.0.0.1", &dest.sin_addr);
int i;
for (i = 0; i < 2000000; ++i) {
sendto(sock, &i, sizeof(i), 0, (const struct sockaddr*)&dest, sizeof(dest));
}
}
// consumer.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
#include <stdio.h>
int main()
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in dest;
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(40500);
inet_aton("127.0.0.1", &dest.sin_addr);
bind(sock, (const struct sockaddr*)&dest, sizeof(dest));
int i;
int buf;
for (i = 0; i < 2000000; ++i) {
recv(sock, &buf, sizeof(buf), 0);
printf("%d %d\n", i, buf);
}
}
I think your problem is the server side process slower than the
sender side.If the receive socket buffer of the server is full,
then the extra packets delivered by the kernel will be droped.
To improve the performance, I think there are several things you
can do:
1.Increase the server side receive buffer.
2.Try use batch send and receive interfaces(eg. sendmmsg(), recvmmsg()).
This will reduce the overhead of system call.
3.Don't call printf() everytime you receive a buffer of data.
It is time consuming.
I used to think that write() system call is unbuffered and that fwrite and fread are used for buffered IO. However I wrote simple programs to establish that some buffering was still going on when using write(). I am using write() and read() on sockets. Due to buffering, it is possible for the client to lag behind while server keeps sending packets. I do not want that. I want that the client must consume the record before the server sends more records.
How can I make that happen without adding network load of acknowledgments etc !
I am using gcc on linux
server.c :
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/tcp.h>
int remote_rr_port=2000; // Server will send RR logs using connection on this port.
char const *remote_server_ip="127.0.0.1";
int connFD_rr;
static void startTcpServer(int *sd, const int port) {
*sd= socket(AF_INET, SOCK_STREAM, 0);
// Set socket option so that port can be reused
int enable = 1;
setsockopt(*sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
struct sockaddr_in a;
memset(&a,0,sizeof(a));
a.sin_family = AF_INET;
a.sin_port = port;
a.sin_addr.s_addr = INADDR_ANY;
int bindResult = bind(*sd, (struct sockaddr *) &a, sizeof(a));
listen(*sd,2);
}
// Wait for connection from client
static int getTcpConnection(int sd) {
char buf[100];
socklen_t len;
struct sockaddr_in clientAddress;
printf("\nWaiting for connection from remote client\n");
len = sizeof(clientAddress);
int connFD = accept(sd, (struct sockaddr*) &clientAddress, &len);
setsockopt(connFD_rr, SOL_SOCKET, SO_SNDBUF, (int[]){0}, sizeof(int));
printf("\n Connection from : %s:%d\n",inet_ntop(AF_INET, &clientAddress.sin_addr, buf, sizeof(buf)),clientAddress.sin_port);
fflush(stdout);
return connFD;
}
FILE* rdrr_server_start(void) {
// Socket Descriptors for the two connections
int rr_sd;
int input_sd;
startTcpServer(&rr_sd, remote_rr_port);
connFD_rr = getTcpConnection(rr_sd);
return fdopen(connFD_rr, "w");
}
int main() {
int i = 0;
rdrr_server_start();
for(i=0;i<10000000; i++) {
write(connFD_rr, &i, sizeof (int));
printf("%d\n", i);
}
return 0;
}
client.c :
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/tcp.h>
int remote_rr_port=2000; // Server will send RR logs using connection on this port.
char const *remote_server_ip="127.0.0.1";
int connFD_rr;
FILE* rdrr_client_start(void) {
connFD_rr = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in a;
memset(&a,0,sizeof(a));
a.sin_family = AF_INET;
a.sin_port = remote_rr_port;
a.sin_addr.s_addr = inet_addr(remote_server_ip);
printf("\nConnecting to Server on RR port");
int CONNECT_TO_SERVER= connect(connFD_rr,(struct sockaddr *) &a, sizeof(a));
printf("\nConnected to server on RR port");
setsockopt(connFD_rr, SOL_SOCKET, SO_RCVBUF, (int[]){0}, sizeof(int));
return fdopen(connFD_rr, "r");
}
int main() {
int i = 0;
rdrr_client_start();
getrchar();
while(1) {
read(connFD_rr, &i, sizeof (int));
printf("%d\n", i);
}
return 0;
}
Perhaps what you mean is that you want to disable Nagle's Algorithm in which case the solution is:
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (int[]){1}, sizeof(int));
Edit: Hmm, it looks like you want more than this, and I doubt what you want is possible without designing your own protocol on top of UDP.
Edit 2: You may be able to get an effect similar to what you want by limiting the send and receive buffer sizes. The server (sender) should do:
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (int[]){YOUR_BUF_LIMIT}, sizeof(int));
and the client (receiver) should do:
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (int[]){YOUR_BUF_LIMIT}, sizeof(int));
I'd like to get a list of available devices (their IP address or hostname should be fine) connected to my local network. I've got some examples in C#, but I couldn't find any sample using C/C++. I'm familiar with the BSD socket API, just to clarify.
I have a "stub" kind of idea: maybe I should determine the range of the IP addresses that the devices on my LAN can potentially belong to, and then determine if they e. g. respond to PING, or something like that. How could I achieve these?
I want my application to run on Linux and iOS. That's why I'd prefer BSD sockets, or at a maximum, Foundation/GNUstep (although they are written in Objective-C).
You can also e.g. send an ICMP echo request packet to 224.0.0.1. This is a special all-nodes multicast address every node should respond to (except if a firewall rule or network policy setting prevents it).
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/ip_icmp.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
// Define the Packet Constants
// ping packet size
#define PING_PKT_S 64
// Automatic port number
#define PORT_NO 0
// Automatic port number
#define PING_SLEEP_RATE 1000000
// Gives the timeout delay for receiving packets
// in seconds
#define RECV_TIMEOUT 1
// Performs a DNS lookup
char *dns_lookup(char *addr_host, struct sockaddr_in *addr_con)
{
//printf("\nResolving DNS..\n");
struct hostent *host_entity;
char *ip=(char*)malloc(NI_MAXHOST*sizeof(char));
int i;
if ((host_entity = gethostbyname(addr_host)) == NULL)
{
// No ip found for hostname
return NULL;
}
//filling up address structure
strcpy(ip, inet_ntoa(*(struct in_addr *)
host_entity->h_addr));
(*addr_con).sin_family = host_entity->h_addrtype;
(*addr_con).sin_port = htons (PORT_NO);
(*addr_con).sin_addr.s_addr = *(long*)host_entity->h_addr;
return ip;
}
// Resolves the reverse lookup of the hostname
char* reverse_dns_lookup(char *ip_addr)
{
struct sockaddr_in temp_addr;
socklen_t len;
char buf[NI_MAXHOST], *ret_buf;
temp_addr.sin_family = AF_INET;
temp_addr.sin_addr.s_addr = inet_addr(ip_addr);
len = sizeof(struct sockaddr_in);
if (getnameinfo((struct sockaddr *) &temp_addr, len, buf,
sizeof(buf), NULL, 0, NI_NAMEREQD))
{
//printf("Could not resolve reverse lookup of hostname\n");
return NULL;
}
ret_buf = (char*)malloc((strlen(buf) +1)*sizeof(char) );
strcpy(ret_buf, buf);
return ret_buf;
}
// Driver Code
int main(int argc, char *argv[])
{
int sockfd;
char *ip_addr, *reverse_hostname;
struct sockaddr_in addr_con;
int addrlen = sizeof(addr_con);
char net_buf[NI_MAXHOST];
int i=0;
for(int i=1;i<255;++i)
{
char ip[80];
sprintf(ip, "192.168.2.%d", i);
ip_addr = dns_lookup(ip, &addr_con);
if(ip_addr==NULL)
{
//printf("\nDNS lookup failed! Could not resolve hostname!\n");
continue;
}
reverse_hostname = reverse_dns_lookup(ip_addr);
if(reverse_hostname==NULL)
{
//printf("\nDNS lookup failed! Could not resolve hostname!\n");
continue;
}
//printf("\nTrying to connect to '%s' IP: %s\n",ip, ip_addr);
printf("\nReverse Lookup domain: %s",
reverse_hostname);
printf("\n %s \n", ip);
}
return 0;
}