コアダンプの数だけ強くなれるよ

見習いエンジニアの備忘log

ソケットプログラミング(UDP)

LinuxUDPによる通信を行うサンプルプログラム。

この手の例はGoogle先生で検索すれば沢山でてくるけど、システムコールのリターン値を見てなかったり、openに対応するcloseをしていない例が多いことに気付くと思う。

もちろん動かすことだけ考えたら気にする必要ないし、この例も完璧とは言えないけど、出来るだけ丁寧な処理を書くことを心がけるようにしたい。



udp_client.c

#include "local.h"

int main(void)
{
    udpSocket_t udp;

    udp.sfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (udp.sfd < 0) {
        PERROR("socket()");
        goto error_end;
    }

    udp.addr.sin_family = PF_INET;
    udp.addr.sin_port = htons(PORTNO);
    udp.addr.sin_addr.s_addr = inet_addr(LOCALHOST);

    char msgbuf[] = "HELLO WORLD\n";
    ssize_t snd = sendto(udp.sfd, msgbuf, sizeof(msgbuf), 0,
                         (struct sockaddr *)&udp.addr, sizeof(udp.addr));
    if (snd < 0) {
        PERROR("sendto()");
        goto close_end;
    }

close_end:
    close(udp.sfd);
error_end:

    return 0;
}


udp_server.c

#include "local.h"

int main(void)
{
    udpSocket_t udp;
    char msgbuf[MSGBUF_SIZE] = {0};

    udp.sfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (udp.sfd < 0) {
        PERROR("socket()");
        goto error_end;
    }

    udp.addr.sin_family = PF_INET;
    udp.addr.sin_port = htons(PORTNO);
    udp.addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(udp.sfd,
             (struct sockaddr *)&udp.addr,
             sizeof(udp.addr)) < 0) {

        PERROR("bind()");
        goto close_end;
    }

    ssize_t rcv = recvfrom(udp.sfd, msgbuf, sizeof(msgbuf), 0,
                           (struct sockaddr*)&udp.addr, &udp.addrlen);
    if (rcv < 0) {
        PERROR("recvform()");
        goto close_end;
    }

    fprintf(stdout, "%s", msgbuf);

close_end:
    close(udp.sfd);
error_end:

    return 0;
}


local.h

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

#define PORTNO  (50001)
#define MSGBUF_SIZE (4096)
#define LOCALHOST "127.0.0.1"

#define PERROR(X) \
{\
    char _strerr[64] = {0};\
    int errcode = errno;\
    \
    strerror_r(errcode, _strerr, sizeof(_strerr));\
    printf(X" failed(%d:%s)\n", errcode, _strerr);\
}

typedef struct {
    int                 sfd;
    struct sockaddr_in  addr;
    socklen_t           addrlen;
} udpSocket_t;

実行例

$ gcc udp_client.c -o client
$ gcc udp_server.c -o server
$ ./server 
$ ./client   #別端末から実行
HELLO WORLD
$