Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm having issues implementing a C UDP socket program. The code below works perfectly with any input shorter than 56 characters, but if I feed it 56 characters or more,
sendto
complains that I gave it invalid arguments (error code 22).
For instance, this will send correctly:
./talkerDemo localhost qqqqqwwwwweeeeeqqqqqwwwwweeeeeqqqqqwwwwweeeeeqqqqqwwwww
But this won't:
./talkerDemo localhost qqqqqwwwwweeeeeqqqqqwwwwweeeeeqqqqqwwwwweeeeeqqqqqwwwwwH
What gives?
** talker.c
** Adapted from http://beej.us/guide/bgnet/html/single/bgnet.html#datagram
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SERVERPORT "4242" // the port users will be connecting to
int main(int argc, char *argv[])
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
break;
if (p == NULL) {
fprintf(stderr, "talker: failed to create socket\n");
return 2;
//============================================================
// !!!!!!! Eror occurs here:
if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
//============================================================
freeaddrinfo(servinfo);
printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);
close(sockfd);
return 0;
This was the version of the code I was actually running. Before posting the question, I had gone back to the original (above) to see if the problem occurred with that implementation too - and I seemed it was. But it turns out I was being thick and was using the wrong binary... derp
** UDPTalker.hpp -- a datagram sockets "server"
** Adapted from http://beej.us/guide/bgnet/html/single/bgnet.html#datagram
#ifndef UDPTALKER_H
#define UDPTALKER_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <iostream>
#include <string>
#define UDPT_DEFAULT_PORT "4243"
#define UDPT_DEFAULT_HOST "localhost"
#define UDPT_MAXBUFLEN 2048
class UDPTalker {
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
std::string host;
std::string port;
public:
//! Takes target hostname/ip and port as arguments. Defaults: ("localhost", "4243")
UDPTalker(std::string host = UDPT_DEFAULT_HOST, std::string port = UDPT_DEFAULT_PORT);
~UDPTalker();
void send(std::string msg);
#endif // UDPTALKER_H
Here's the corresponding .cpp
:
// File UDPTalker.cpp
#include "UDPTalker.hpp"
UDPTalker::UDPTalker(std::string h, std::string port) : host(h), port(port) {
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(host.c_str(), port.c_str(), &hints, &servinfo)) != 0) {
throw std::runtime_error(std::string("getaddrinfo: ").append(gai_strerror(rv)));
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
break;
freeaddrinfo(servinfo);
if (p == NULL) {
throw std::runtime_error("talker: failed to create socket\n");
UDPTalker::~UDPTalker() {
close(sockfd);
void UDPTalker::send(std::string msg) {
if ((numbytes = sendto(sockfd, msg.c_str(), msg.size(), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto! ");
// printf("talker: sent %d bytes to %s\n", numbytes, host.c_str());
–
–
–
–
–
freeaddrinfo(servinfo);
frees up the memory used by servinfo
. This means that the pointer p
is now pointing to empty memory, so when it gets passed to sendto
it may have invalid content. My guess is that for some reason the extra byte in the input string was "rolling over" that memory location when the class' send
method was being called. The fix was moving freeaddrinfo(servinfo);
from the constructor to the destructor:
UDPTalker::UDPTalker(std::string h, std::string port) : host(h), port(port) {
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(host.c_str(), port.c_str(), &hints, &servinfo)) != 0) {
throw std::runtime_error(std::string("getaddrinfo: ").append(gai_strerror(rv)));
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
break;
if (p == NULL) {
throw std::runtime_error("talker: failed to create socket\n");
UDPTalker::~UDPTalker() {
freeaddrinfo(servinfo);
close(sockfd);
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.