TCP送受信方法

以前、UDPはやったから、やっぱりTCPもやっておかないとね・・・と。

UDPでもTCPでも変わらない様な内容は UDP送受信方法参照 ということで。

  1. ソケットの初期化
  2. 接続
  3. 接続
  4. 送受信
  5. サンプルコード
  6. ネタもと
  7. 履歴

ソケットの初期化

UDPの場合と同様に、まずはソケットの生成を行います。細かい説明は UDP送受信方法参照 です。

int socket ( int domain, int type, int protocol );

TCPに依る通信を行う場合は、type を SOCK_STREAM に設定します。

 

接続

「接続指向」なTCPを使用する際には、送受信を行う前に接続を行う必要が有ります。

接続していない状態では、後述する送受信などの処理が行えません。

 

又、「非接続指向」なUDP通信を行う際にも connect を実行することが可能です。

# 「必要」な訳ではないです

その場合では、実際に接続が行われる訳ではなく、単純に送信先 or 受信元を設定するということになり、送受信の処理に send や recv を使用することが出来るようになります。

# 受信する際は、connect していないソケットから受信した場合は破棄されます。

int connect ( int sock, const struct sockaddr *serv_addr, socklen_t addrlen );

成功時は 0 を、エラー時には -1 が返ります(Winsock では、SOCKET_ERROR)。

sock にはソケットディスクリプタを指定します。

 

servaddr 接続先のアドレス情報を指定し、addrlen には servaddr のサイズを指定します。

UDPでの sendto の時に指定した物をあらかじめ、という感じです

 

また、TCPの様な「接続指向」ソケットの場合は二度目以降の connect は失敗します。

UDPの様な「非接続指向」ソケットの場合は、何度やっても相手先を設定し直すだけで失敗はしません。

 

接続待ち

例えばクライアント側で connect を行う場合、サーバ側では connect されるのを待ちます。

この際、受信待ちを行う listen と実際に接続要求を受け入れる accept の二種類の関数を使用することになります。

    int listen ( int sock, int backlog );
    int accept ( int sock, struct sockaddr *from, socklen_t *fromlen );

listen の返値は、成功時 0 が返ります。

accept の返値は connect されたソケットを複製した新規のソケットディスクリプタ。

共にエラー時には -1 が返ります(Winsock では、SOCKET_ERROR)。

 

sock には受信待ちを行うソケットディスクリプタを指定します。

 

listen の backlog には接続を受け付ける為のキューの最大長を指定します。

# Linux2.2以上では、受付待ちになっているセッションが確立済みのソケットキュー。確立待ちのソケットキューは sysctl 又は syncookie(kernel設定)で設定する。

 

accept の from にはアドレス構造体のポインタを、fromlen にはそのサイズを指定する socklent のポインタを指定します。(WinSockでは、socklent は無いので int です。)

因みに、fromlen は入出力両方に使用されます(要するに、関数内部では fromlen の値が from に書き込めるサイズとして認識され、accept から返ったときには fromlen はflom に格納されたサイズを示す)

 

accept で取得したソケットディスクリプタは、元のソケットディスクリプタに設定されていたフラグ(fcntlなどで設定)は継承されないことに注意。

 

送受信

接続されたソケットに対する送信は、 UDPの場合 とは違い送信先を指定する必要がありません。

ssize_t send ( int sock, const void *buf, size_t len, int flags );

返値は送信したデータのバイト数。

エラー時には -1 が返ります(Winsock では、SOCKET_ERROR)。

 

sock にはソケットディスクリプタを指定します。

buf には送信したいデータのポインタを、len にはそのデータのサイズを指定します。

flags にはフラグを指定します。これは、 UDPの場合 と同じです。

 

送信と同様に、受信も UDPの場合 と違い、受信元を指定する必要がありません。

# まぁ、recvfrom ( s, buf, sizeof(buf), flag, NULL, NULL ); と同等ですが。

ssize_t recv ( int sock, void *buf, size_t len int flags );

返値は受信したデータのバイト数。

エラー時には -1 が返ります(Winsock では、SOCKET_ERROR)。

もし返値が 0 の場合が有れば、それもエラーの可能性が有ります(相手側で close されたとか)。

 

sock にはソケットディスクリプタを指定します。

buf には受信データを格納するバッファのアドレス、len にはバッファのサイズを指定します。

flags にはフラグを指定します。これも、 UDPの場合 と同じです。

 

サンプルコード

ごめん、まだ出来てないm(_ _)m

とりあえず作って試したら core 吐いた(哀

 

ネタ元

履歴

  • 2003/03/03 とりあえず公開
  • 2005/01/05 IPv6対応等

- スポンサードリンク -