コンテンツにスキップ

ソケット (BSD)

出典: フリー百科事典『ウィキペディア(Wikipedia)』

: socketBSDUNIXAPIC調BSD

communication endpoint[1][2][3][4][5][6][7]API

1983UNIX (OS) 4.2BSD  API Socket APIC[ 1]

APISTREAMS Transport Layer Interface (TLI) BSD

BSD[]


BSD1TCP/IPUNIXBSD

3 RAWRAW使

socketprotocol familysocket type[9]Linux20protocol familyIPv4AF_INETUNIXAF_UNIXprotocol family<sys/socket.h>[10]socket typeSOCK_STREAMSOCK_DGRAMfamilysocket
表. プロトコルとの関係
row:family/column:type SOCK_STREAM SOCK_DGRAM
AF_INET/AF_INET6 TCP UDP
AF_UNIX UNIXドメインソケット UNIXドメインソケット

ヘッダファイル[編集]


BSD

<sys/socket.h>

BSD

<netinet/in.h>

AF_INET  AF_INET6 使IPTCP/UDP

<sys/un.h>

AF_UNIX 使使

<arpa/inet.h>

IP

<netdb.h>

DNS

TCP[]


TCP TCP socket()  AF_INET  AF_INET6  SOCK_STREAM 

[]


TCP

TCPsocket()

 listenbind()bind() sockaddr_in bzero()  memset() sin_family  AF_INET  AF_INET6 sin_port  listen short int htons() 使

 listen 使listen() 

 accept()  listen accept() 

send()recv()write()read()使

close() 使fork() 使

C99 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void)
{
    // サーバーソケット作成
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        perror("socket");
        return 1;
    }

    // struct sockaddr_in 作成
    struct sockaddr_in sa = {0};
    sa.sin_family = AF_INET;
    sa.sin_port = htons(1100);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);

    // バインド
    if (bind(sock, (struct sockaddr*) &sa, sizeof(struct sockaddr_in)) == -1)
    {
        perror("bind");
        goto bail;
    }

    // リッスン
    if (listen(sock, 128) == -1)
    {
        perror("listen");
        goto bail;
    }

    while (1)
    {
        // クライアントの接続を待つ
        int fd = accept(sock, NULL, NULL);
        if (fd == -1)
        {
            perror("accept");
            goto bail;
        }

        // 受信
        char buffer[4096];
        int recv_size = read(fd, buffer, sizeof(buffer) - 1);
        if (recv_size == -1)
        {
            perror("read");
            close(fd);
            goto bail;
        }

        // 受信内容を表示
        buffer[recv_size] = '\0';
        printf("message: %s\n", buffer);

        // ソケットのクローズ
        if (close(fd) == -1)
        {
            perror("close");
            goto bail;
        }
    }

bail:
    // エラーが発生した場合の処理
    close(sock);
    return 1;
}

クライアント[編集]


TCP

TCPsocket()

connect() sockaddr_in  sin_family  AF_INET  AF_INET6 sin_port  listen sin_addr IPv4  IPv6 

send()recv()write()read()使

 close() fork() 使

C99 
#define _BSD_SOURCE

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MESSAGE "Hello World!"

int main(void)
{
    // ソケット作成
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        perror("socket");
        return 1;
    }

    // struct sockaddr_in 作成
    struct sockaddr_in sa = {0};
    sa.sin_family = AF_INET;
    sa.sin_port = htons(1100);

    // localhost の IP アドレスを引く
    struct hostent *hostent = gethostbyname("localhost");
    if (hostent == NULL)
    {
        herror("gethostbyname");
        goto bail;
    }
    memcpy(&sa.sin_addr, hostent->h_addr_list[0], sizeof(sa.sin_addr));

    // 接続
    if (connect(sock, (struct sockaddr*) &sa, sizeof(struct sockaddr_in)) == -1)
    {
        perror("connect");
        goto bail;
    }

    // 送信
    if (write(sock, MESSAGE, strlen(MESSAGE)) == -1)
    {
    	perror("write");
    	goto bail;
    }

    // クローズ
    close(sock);
    return 0;
 
bail:
    // エラーが発生した場合の処理
    close(sock);
    return 1;
}

 gcc  -std=c99 -std=gnu99 使 #define _BSD_SOURCE #define _BSD_SOURCE  herror() 使

UDP[]


UDP UDP1UDP  TCP 2datagram

UDP UDPTCP

[]


C99  7654  UDP 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
 
int main(void)
{
    // ソケット作成
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1)
    {
        perror("socket");
        return 1;
    }

    // struct sockaddr_in 作成
    struct sockaddr_in sa = {0};
    sa.sin_family = AF_INET;
    sa.sin_port = htons(7654);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);

    // バインド
    if (bind(sock, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) == -1)
    {
        perror("bind");
        goto bail;
    }

    while (1)
    {
        // 受信
        char buffer[4096];
        socklen_t addrlen = sizeof(struct sockaddr_in);
        ssize_t recv_size = recvfrom(sock, (void *) buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &sa, &addrlen);
        if (recv_size == -1)
        {
            perror("recvfrom");
            goto bail;
        }

        // 受信内容表示
        buffer[recv_size] = '\0';
        printf("datagram: %s\n", buffer);
    }
 
bail:
    // エラーが発生した場合の処理
    close(sock);
    return 1;
}

bind() は、ソケットとアドレス/ポートを結びつける。

最後の無限ループは recvfrom() を使ってポート番号 7654 からのUDPパケットを受信する。引数は以下の通り。

  • ソケット
  • バッファへのポインタ
  • バッファの大きさ
  • フラグ(read などの他のソケット受信関数と同じ)
  • アドレス構造体
  • アドレス構造体の大きさ

クライアント[編集]

C99 でのクライアント側のソースコード。ポート 7654、アドレス 127.0.0.1 に "Hello World!" という内容の UDP パケットを送る。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MESSAGE "Hello World!"

int main(void)
{
    // ソケット作成
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1)
    {
        perror("socket");
        return 1;
    }

    // struct sockaddr_in 作成
    struct sockaddr_in sa = {0};
    sa.sin_family = AF_INET;
    sa.sin_port = htons(7654);
    sa.sin_addr.s_addr = inet_addr("127.0.0.1");

    // 送信
    int bytes_sent = sendto(sock, MESSAGE, strlen(MESSAGE), 0, (struct sockaddr*) &sa, sizeof(struct sockaddr_in));
    if (bytes_sent == -1)
    {
        perror("sendto");
        goto bail;
    }

    // クローズ
    close(sock);
    return 0;

bail:
    // エラーが発生した場合の処理
    close(sock);
    return 1;
}

UNIXドメインソケット[編集]


IPIPUNIX

[]

socket()[]


socket() socket() 3

domain - 
AF_INET - IPv4

AF_INET6 - IPv6

AF_UNIX - UNIX

type - 
SOCK_STREAM - TCP

SOCK_DGRAM - UDP

SOCK_SEQPACKET - SOCK_STREAM

SOCK_RAW - IP使

protocol -  0 domain  type TCPAF_INET  AF_INET6  SOCK_STREAMUDP AF_  SOCK_DGRAM <netinet/in.h> 

 -1 
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

gethostbyname() と gethostbyaddr()[編集]


gethostbyname()  gethostbyaddr()  struct hostent /etc/hosts /etc/hosts 

name -  "www.wikipedia.org"

addr - in_addr 

len - addr 

type - AF_INET

NULLh_errno  struct hostent * 
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const void *addr, int len, int type);

connect()[編集]

connect() はコネクションの確立に成功すると 0 を返し、エラーが発生すると -1 を返す。

コネクションレスのソケットの場合(User Datagram Protocol)、connect() は送受信の相手を指定するのに使われ、send()recv() をコネクションレスのソケットで使えるようになる。

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind()[編集]

bind() はソケットにアドレスを設定する。socket() で生成された時点では、ソケットはアドレスファミリは指定されているが、アドレスは設定されていない。ソケットは、コネクションを受け付ける前にバインド(アドレス設定)される必要がある。以下の引数がある。

  • sockfd - バインドすべきソケットの記述子
  • addr - バインドすべきアドレスを表す sockaddr 構造体へのポインタ
  • addrlen - sockaddr 構造体の大きさ

成功すると 0 を返し、エラーが発生すると -1 を返す。

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

listen()[編集]

listen() はバインドされたソケットでコネクション確立要求を待ち受ける。SOCK_STREAM または SOCK_SEQPACKET の場合のみ有効。以下の引数がある。

  • sockfd - ソケット記述子
  • backlog - ある時点でペンディングにできる(キューイングできる)最大コネクション数。一般にOSが上限を設けている。

コネクションは accept() されるとデキューされる。成功すると 0 を返す。エラーが発生すると -1 を返す。

#include <sys/socket.h>
int listen(int sockfd, int backlog);

accept()[編集]


accept() 

sockfd - listen 

addr -  accept()  sockaddr 

addrlen - addr  sockaddr  socklen_t accept() 

 -1 
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

ブロッキングとノンブロッキング[編集]


BSD2 listen 

fcntl()  ioctl() 使

[]


socket()  close() 使connect() socket()  close() close 使 <unistd.h> 

[]


 POSIX 

IEEE Std. 1003.1-2001 Standard for Information Technology -- Portable Operating System Interface (POSIX).

Open Group Technical Standard: Base Specifications, Issue 6, December 2001.

ISO/IEC 9945:2002

the Austin website 

APIIPv6RFC 3493  RFC 3542 

2008111Free On-line Dictionary of ComputingGFDL 1.3RELICENSING() 

脚注[編集]

注釈[編集]

  1. ^ 代表的なものとして、Javajava.net.Socketクラスや、.NETSystem.Net.Sockets.Socketクラス[8]が挙げられる。

出典[編集]



(一)^  2003C UNIX ISBN 978-4-274-06499-9 p. 422

(二)^ Stevens, William RichardA.Rago, Stephen16 IPC: UNIX3 160-0006 宿52014421201354551ISBN 9784798134888https://www.shoeisha.co.jp/book/detail/9784798134888201893 

(三)^  - IBM Documentation

(四)^  - Trusted Extensions 

(五)^ Communication Endpoints - Trusted Extensions Developer's Guide

(六)^ TCP/IP :  - IBM Documentation

(七)^  ? - IBM Documentation

(八)^ Socket Class (System.Net.Sockets) | Microsoft Learn

(九)^ The protocol modules are grouped into protocol families such as AF_INET, AF_IPX, and AF_PACKET, and socket types such as SOCK_STREAMorSOCK_DGRAM. SOCKET(7)

(十)^ These families are defined in <sys/socket.h> SOCKET(2)

関連項目[編集]

外部リンク[編集]