Skip to content

Instantly share code, notes, and snippets.

@hiroshiro
Last active August 29, 2015 14:16
Show Gist options
  • Save hiroshiro/88a9dc9997a6ebd0f916 to your computer and use it in GitHub Desktop.
Save hiroshiro/88a9dc9997a6ebd0f916 to your computer and use it in GitHub Desktop.
LinuxネットワーキングプログラミングバイブルTCP/IPプログラミング入門Chapter03 getaddinf()を利用しないserver_socket()IP4
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
/* send_recv_loopの定義 */
void send_recv_loop(int);
/* サーバーソケットの準備 */
int server_socket(const char *portnm)
{
struct sockaddr_in my;
int soc, portno, opt;
socklen_t opt_len;
struct servent *se;
/* アドレス情報を0クリア */
(void) memset(&my, 0, sizeof(my));
my.sin_family = AF_INET;
my.sin_addr.s_addr = htonl(INADDR_ANY);
/* ポート番号の決定 */
if (isdigit(portnm[0])) {
/* 先頭が数字 */
if (( portno = atoi(portnm)) <= 0) {
/* 数値化するとゼロ以下 */
(void) fprintf(stderr, "bad port no\n");
return (-1);
}
my.sin_port = htons(portno);
} else {
if ((se = getservbyname(portnm, "tcp")) == NULL) {
/* サービスに見つからない */
(void) fprintf(stderr, "getservent():error\n");
return (-1);
} else {
/* サービス見つかった:該当ポート番号 */
my.sin_port = se->s_port;
}
}
(void) fprintf(stderr, "port=%d\n", ntohs(my.sin_port));
/* ソケットの生成 */
if ((soc = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
return (-1);
}
/* ソケットオプション(再利用フラグ)設定 */
opt = 1;
opt_len = sizeof(opt);
if (setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, &opt, opt_len) == -1) {
perror("setsockopt");
(void) close(soc);
return (-1);
}
/* ソケットにアドレスを指定 */
if (bind(soc, (struct sockaddr *) &my, sizeof(my)) == -1) {
perror("bind");
(void) close(soc);
return (-1);
}
/* アクセスバッグログの指定 */
if (listen(soc, SOMAXCONN) == -1) {
perror("listen");
(void) close(soc);
return (-1);
}
return (soc);
}
/* アクセプトループ */
void accept_loop(int soc)
{
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
struct sockaddr_storage from;
int acc;
socklen_t len;
for(;;){
len = (socklen_t) sizeof(from);
/* 接続受付 */
if (( acc = accept(soc, (struct sockaddr *) &from, &len)) == -1) {
if (errno != EINTR) {
perror("accept");
}
} else {
(void) getnameinfo((struct sockaddr *) &from, len,
hbuf, sizeof(hbuf),
sbuf, sizeof(sbuf),
NI_NUMERICHOST | NI_NUMERICSERV);
(void) fprintf(stderr, "accept:%s:%s\n",hbuf, sbuf);
/* 送受信ループ */
send_recv_loop(acc);
/* アクセプトソケットクローズ */
(void) close(acc);
acc = 0;
}
}
}
/* サイズ指定文字列連結 */
size_t mystrlcat(char *dst, const char *src, size_t size)
{
const char *ps;
char *pd, *pde;
size_t dlen, lest;
for (pd = dst, lest = size; *pd != '\0' && lest != 0; pd++, lest--);
dlen = pd - dst;
if (size - dlen == 0) {
return (dlen + strlen(src));
}
pde = dst + size - 1;
for (ps = src; *ps != '\0' && pd < pde; pd++, ps++) {
*pd = *ps;
}
for (; pd <= pde; pd++) {
*pd = '\0';
}
while (*ps++);
return (dlen = (ps - src - 1));
}
/* 送受信ループ */
void send_recv_loop(int acc)
{
char buf[512], *ptr;
ssize_t len;
for (;;) {
/* 受信 */
if ((len = recv(acc, buf ,sizeof(buf), 0)) == -1) {
/* エラー */
perror("recv");
break;
}
if (len == 0) {
(void) fprintf(stderr, "recv:EOF\n");
break;
}
/* 文字列化・表示 */
buf[len] = '\0';
if((ptr = strpbrk(buf, "\r\n")) != NULL) {
*ptr = '\0';
}
(void) fprintf(stderr, "[client]%s\n", buf);
/* 応答文字列作成 */
(void) mystrlcat(buf, ":OK\r\n", sizeof(buf));
len = (ssize_t) strlen(buf);
/* 反応 */
if ((len = send(acc, buf, (size_t) len, 0)) == -1) {
/* エラー */
perror("send");
break;
}
}
}
int main(int argc, const char *argv[])
{
int soc;
/* 引数にポート番号がしていされているか? */
if (argc <= 1) {
(void) fprintf(stderr, "server port\n");
return (EX_USAGE);
}
/* サーバーソケットの準備 */
if ((soc = server_socket(argv[1])) == -1) {
(void) fprintf(stderr, "server_socket(%s):error\n", argv[1]);
return (EX_UNAVAILABLE);
}
(void) fprintf(stderr, "ready for accept\n");
/* アクセプトループ */
accept_loop(soc);
/* ソケットクローズ */
(void) close(soc);
return (EX_OK);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment