socketプログラミングsend()recv()sendto()recvfrom()

11438 ワード

socketプログラミングsend()recv()sendto()recvfrom()
int socket( int af, int type, int protocol); af:プロトコルクラスタ(プロトコルドメイン)を指定し、よくあるAF_INET-IPv 4プロトコルとして指定され、AF_INET 6-IPv 6、AF_に指定LOCAL:UNIXプロトコルドメインなどに指定します.この値は、システムが事前に定義したマクロであり、システムがどのプロトコルをサポートしているかを使用できます.そうしないと、呼び出しに失敗します.プロトコルクラスタは、ネットワーク層のプロトコルtype:socketタイプを指定し、一般的なsocketタイプは、TCP(SOCK_STREAM)、UDP(SOCK_DGRAM)、SOCK_SEQPACKET、SOCK_RAWなどは,バイトストリーム,データレポート,秩序化パケット,元のソケットインタフェースをそれぞれ示す.これは実際にカーネルが提供するサービス抽象を指定します(各プロトコルクラスタがここのすべてのタイプをサポートしているわけではないので、タイプはプロトコルクラスタと一致することに注意してください).protocol:対応する転送プロトコル、すなわちTCPまたはUDPプロトコルなどを指定し、システムは各プロトコルクラスタとタイプに対してデフォルトのプロトコルを提供する(protocolは0に設定してデフォルトのプロトコルを使用する).一般的なプロトコル:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等は、TCPトランスポートプロトコル、UDPトランスポートプロトコル、STCPトランスポートプロトコル、TIPCトランスポートプロトコルにそれぞれ対応する.
SOCK_STREAMタイプ:秩序ある、信頼性の高い、双方向の、および接続ベースのバイトストリームを提供し、帯域外データ転送メカニズムを使用し、インターネットアドレスファミリーにTCPを使用する.SOCK_STREAMタイプのソケットは全双方向のバイトストリームである.ストリーム・クラス・スイート・インタフェースでは、データを受信または送信する前に接続済みである必要があります.接続()呼び出しで別のインタフェースとの接続を確立し、接続に成功するとsend()とrecv()でデータを転送できます.セッションが終了するとclosesocket()が呼び出されます.帯域外データは規定に従ってsend()とrecv()で受信する.SOCK_を実現STREAMタイプのソケットインタフェースの通信プロトコルは、データが失われず、重複しないことを保証します.端末プロトコルにバッファ容量があり、データが一定時間で正常に送信されない場合、接続が中断されたとみなされ、その後の呼び出しもWSAAETIMEOUTエラーで返されます.SOCK_DGRAMタイプ:接続なし、信頼性の低い、固定サイズ(通常は小さい)バッファを使用するデータ・レポート・サービスをサポートし、インターネット・アドレス・ファミリーにUDPを使用します.SOCK_DGRAMタイプスイートインタフェースでは、sendto()およびrecvfrom()を使用して任意のポートからデータ・レポートを送信または受信できます.このようなインタフェースセットがconnect()で指定されたポートに接続されている場合、send()およびrecv()を使用してそのポートとデータレポートの送信および受信を行うことができます.
一般的にはsend()、recv()はTCP、sendto()およびrecvfrom()はUDPに使用されますが、send()、recv()はUDP、sendto()およびrecvfrom()はTCPにも使用できます
1、 int send(SOCKET s, const char FAR *buf, int len, int flags); 機能:TCP接続の反対側にデータを送信し、クライアントプログラムは一般的にsend関数でサーバに要求を送信し、サーバは通常send関数でクライアントプログラムに応答を送信する.s:送信側ソケット記述子を指定する.buf:アプリケーションがデータを送信するバッファを格納することを示す.len:実際に送信するデータのバイト数を示す.flags:一般的に0に設定します.同期Socketのsend関数の実行フローのみを説明する:1、この関数を呼び出すと、sendはまず送信対象データの長さlenとソケットsの送信バッファの長さを比較し、lenがsの送信バッファの長さより大きい場合、この関数はSOCKET_を返すERROR; lenがsの送信バッファの長さ以下である場合、sendはまずプロトコルがsの送信バッファのデータを送信しているかどうかをチェックし、プロトコルがデータを送信するのを待つ場合、プロトコルがsの送信バッファのデータを送信し始めていない場合、またはsの送信バッファにデータがない場合、sendはsの送信バッファの残りの空間とlenを比較する.lenが余剰空間サイズsendより大きい場合、プロトコルがsの送信バッファのデータを送信するのを待つ.lenが余剰空間サイズsendより小さい場合、bufのデータcopyだけを余剰空間に送る(sendはbufのデータcopyをsの送信バッファの余剰空間に送るだけで、プロトコルは伝送を完了する).2、send関数copyデータが成功した場合、実際のcopyのバイト数を返し、sendがcopyデータの時にエラーが発生した場合、sendはSOCKET_を返すERROR; sendがプロトコル転送待ちでネットワークが切断された場合、send関数もSOCKET_を返すERROR.
注意:1、send関数はbufのデータをsの送信バッファの残りの空間にcopyすることに成功した後、戻ってきたが、この場合、これらのデータはすぐに接続の反対側に伝わるとは限らない.プロトコルがその後の転送中にネットワークエラーが発生した場合、次のSocket関数はSOCKET_を返します.ERROR. 2、send以外の各Socket関数は、実行の最初にソケットの送信バッファのデータがプロトコルによって転送されるのを待つ必要があります.待機中にネットワークエラーが発生した場合、そのSocket関数はSOCKET_を返します.ERRORはUnixシステムにおいて、sendがプロトコル転送待ちでネットワークが切断された場合、sendを呼び出すプロセスはSIGPIPE信号を受信し、プロセスのデフォルト処理はプロセス終了である.(unix/linuxカーネルのシステムでは、プログラマがこのような状況を処理します.そうしないと、プログラムは意外に終了します).
2、 int recv(SOCKET s, char FAR *buf, int len, int flags); 機能:TCP接続の他端からデータを受信し、クライアント、サーバ側アプリケーションはrecv関数でデータsを受信する:受信側ソケット記述子を指定する;buf:recv関数で受信したデータを格納するためのバッファを示す.len:bufの長さを示す;flags:一般的に0に設定します.同期Socketのrecv関数の実行フローのみを説明する:1、recv関数を呼び出すと、recvはsの送信バッファのデータがプロトコルによって転送されるのを先に待つ.もしプロトコルがsの送信バッファのデータを転送する時にネットワークエラーが発生したら、recv関数はSOCKET_を返すERRORは、sの送信バッファにデータがないか、プロトコルによってデータが正常に送信された後、recvはソケットsの受信バッファをチェックし、s受信バッファにデータがないか、プロトコルがデータを受信している場合、recvはプロトコルがデータを受信するまで待機します.2、プロトコルがデータを受信し終わると、recv関数はsの受信バッファの中のデータcopyをbufの中に入れる(プロトコルが受信したデータはbufの長さより大きいかもしれないが、この時に何回かrecv関数を呼び出してこそsの受信バッファの中のデータcopyを完成させることができる.recv関数はcopyがデータを出すだけで、本当の受信データはプロトコルが完成する)、3、recv関数は、実際のcopyのバイト数を返します.
recvがcopyでエラーが発生した場合、SOCKET_を返します.ERROR; recv関数がプロトコルがデータを受信するのを待っている間にネットワークが中断した場合、0が返されます.
注:Unixシステムでは、recv関数がプロトコルの受信待ち中にネットワークが切断された場合、recvを呼び出すプロセスはSIGPIPE信号を受信し、プロセスのデフォルト処理はプロセス終了(unix/linuxカーネルのシステムでは、プログラミング者がこのような状況を処理しないと、プログラムは意外に終了します).
3、//接続のないデータレポートsocket方式では、ローカルsocketがリモートマシンと接続を確立していないため、データ送信時に明目のアドレスint sendto(int sockfd,const void*msg,int len,unsigned int flags,const struct sockaddr*to,int tolen)を指すべきである.to:宛先機のIPアドレスとポート番号情報を表し、tolen:sizeof(struct sockaddr)としてしばしば付与される.sendto関数も、実際に送信されたデータバイト長を返すか、送信エラーが発生した場合に−1を返す.
4、 int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); from:struct sockaddrタイプの変数で、ソースマシンのIPアドレスとポート番号を保存します.fromlen:sizeof(struct sockaddr)に常設されている.recvfrom()が返されると、fromlenには実際にfromに格納されたデータバイト数が含まれます.recvfrom()関数は、受信したバイト数またはエラーが発生した場合に-1を返し、対応するerrnoを設定します.
説明:1、sendto()およびrecvfrom()は一般的にUDPプロトコルで使用されるが、TCPでconnect関数が呼び出された後もTCP転送に使用される:2、データグラムsocketに対してconnect()関数が呼び出された場合、send()およびrecv()を使用してデータ転送を行うこともできるが、このsocketは依然としてデータグラムsocketであり、転送層のUDPサービスを利用する.ただし、データ・レポートの送信または受信時には、カーネルに宛先とソース・アドレス情報が自動的に追加されます.
使用例:udp serverエンドプログラム:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define UDP_TEST_PORT       10000

int main(int argC, char* arg[])
{
    struct sockaddr_in addr;
    int sockfd, len = 0;    
    int addr_len = sizeof(struct sockaddr_in);
    char buffer[256];   

    //  socket,   SOCK_DGRAM 
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror ("socket");
        exit(1);
    }

    //   sockaddr_in   
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(UDP_TEST_PORT); //  16                 
    addr.sin_addr.s_addr = htonl(INADDR_ANY) ;//     IP     

    //   socket 
    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))<0) {
        perror("connect");
        exit(1);
    }

    while(1) {
        bzero(buffer, sizeof(buffer));
        len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&addr ,&addr_len);
        //   client                
        printf("Received a string from client %s, string is: %s
"
, inet_ntoa(addr.sin_addr), buffer); // client sendto(sockfd,buffer, len, 0, (struct sockaddr *)&addr, addr_len); } return 0; }

udpクライアントエンドプログラム:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define UDP_TEST_PORT       10000
//#define UDP_SERVER_IP   "127.0.0.1"

int main(int argC, char* arg[])
{
    struct sockaddr_in addr;
    int sockfd, len = 0;    
    int addr_len = sizeof(struct sockaddr_in);      
    char buffer[256];

    //   socket,     SOCK_DGRAM 
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        exit(1);
    }

    //   sockaddr_in
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(UDP_TEST_PORT); //   16                 
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //                      (      )

    strcpy(buffer, "Hello World!");
    len = sizeof(buffer);

    while(1) {
        //bzero(buffer, sizeof(buffer));
        //printf("Please enter a string to send to server: 
");
// //len = read(STDIN_FILENO, buffer, sizeof(buffer)); // server sendto(sockfd, buffer, len, 0, (struct sockaddr *)&addr, addr_len); // server len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &addr_len); printf("Receive from server: %s
"
, buffer); msleep(1000); } return 0; }