ampersander
ampersander

Reputation: 288

Only first UDP packet sent, then connection refused

I managed to make a reproducible example (All includes from my large original source code remain). The thing is that only the first letter a is sent. Then, I get send() failed: Connection refused. I don't know what to do, this is literally the smallest code that should work.

I should say that the code does not work only if I open the socket once at the beginning of the program and close it at the end of the program. If I open a socket for each individual send() and then close it right afterwards, no error comes up.

#include <pcap.h>
#include <cstdio>
#include <getopt.h>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <map>
#include <vector>

#define BUFSIZE 256

#define __FAVOR_BSD

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include<netdb.h>
#include<err.h>

#include <arpa/inet.h>

#include <netinet/ether.h>

#include <netinet/ip.h>
#include <netinet/ip6.h>

#include <netinet/tcp.h>
#include <netinet/udp.h>

#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>



using namespace std;

#define BUFFER 1024                // buffer length
int sock;                        // socket descriptor

void start_connection(){
    struct sockaddr_in server, from; // address structures of the server and the client
    struct hostent *servent;         // network host entry required by gethostbyname()

    memset(&server,0,sizeof(server)); // erase the server structure
    server.sin_family = AF_INET;

    // make DNS resolution of the first parameter using gethostbyname()
    if ((servent = gethostbyname("127.0.0.1")) == NULL) // check the first parameter
        errx(1,"gethostbyname() failed\n");

    // copy the first parameter to the server.sin_addr structure
    memcpy(&server.sin_addr,servent->h_addr,servent->h_length);

    server.sin_port = htons(2055);
    if ((sock = socket(AF_INET , SOCK_DGRAM , 0)) == -1)   //create a client socket
        err(1,"socket() failed\n");

    // create a connected UDP socket
    if (connect(sock, (struct sockaddr *)&server, sizeof(server))  == -1)
        err(1, "connect() failed");
}

void send_data(char * string){
    char buffer[BUFFER];
    int msg_size,i;

    //send data to the server
    memcpy(buffer,string,2);
    msg_size=2;
    i = send(sock,buffer,msg_size,0);     // send data to the server
    if (i == -1)                   // check if data was sent correctly
        err(1,"send() failed");
    else if (i != msg_size)
        err(1,"send(): buffer written partially");
    printf("%s",string);

}


int main(int argc, char *argv[])
{

    //Start UDP connection
    start_connection();

    send_data("a");
    send_data("b");
    send_data("c");

    //Close the UDP connection
    close(sock);
    return 0;
}

Upvotes: 0

Views: 340

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123260

UDP does not provide a real reliable connection. connect just sets the destination address. A send will only put the data into the send buffer and will only fail if there was a previous error on the socket.

The first send will not fail, since no previous activity was done on the socket and thus not error could have happend.

But ... the datagram is then send to the target system. If the target system or some firewall in between rejects the packet with ICMP unreachable, then an error will be set on the socket. This error will then be delivered to the application on the next system call on the socket - in this case the second send.

Thus, what you observe will for example happen if there is no UDP server expecting packets on the specific IP and port or if some firewall is explicitly blocking the packets. As explained, you get the error only on the second send.

Upvotes: 7

Related Questions