TCP送受信方法
以前、UDPはやったから、やっぱりTCPもやっておかないとね・・・と。
UDPでもTCPでも変わらない様な内容は UDP送受信方法参照 ということで。
ソケットの初期化
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対応等
- スポンサードリンク -