ソケットプログラミング(UDP)
LinuxでUDPによる通信を行うサンプルプログラム。
この手の例は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
$
コメント