ソケットプログラミング(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 $