Linux c開発-Socket
11544 ワード
Socketの英語の原義は「穴」または「コンセント」です.BSD UNIXのプロセス通信メカニズムとして,次の意味をとる.通常は「ソケット」とも呼ばれ、IPアドレスとポートを記述するために使用され、通信チェーンのハンドルである.インターネット上のホストでは、一般的に複数のサービスソフトウェアが実行され、いくつかのサービスが提供されています.各サービスはSocketを開き、異なるポートが異なるサービスに対応するポートにバインドされます.
サービス側の例
まず、マルチスレッド、マルチユーザ接続をサポートするブロックIOモードのSOCKETの例を見る.なぜIOがブロックされているのか、私の文章を参考にしてください.http://blog.csdn.net/initphp/article/details/42011845
スレッドが使用されているため、例のコンパイル:
クライアントの例
クライアントの例を見ることができます.この例は主にsocketによってサービス側に接続され、サービス側にメッセージを送信し、応答を受信する.
共通インタフェース
1.socket()関数
関数の定義:
パラメータ:
1.domainは、どのアドレスタイプを使用するかを指定します.
プロトコル
説明
PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL
UNIXプロセス通信プロトコル
PF_INET/AF_INET
Ipv 4ネットワークプロトコル
PF_INET6/AF_INET6
Ipv 6ネットワークプロトコル
PF_IPX/AF_IPX IPX-Novell
プロトコル
PF_NETLINK/AF_NETLINK
コアユーザインタフェース装置
PF_X25/AF_X25
ITU-T X.25/ISO-8208プロトコル
PF_AX25/AF_AX25
アマチュア無線AX25プロトコル
PF_ATMPVC/AF_ATMPVC
元ATM PVCsへのアクセス
PF_APPLETALK/AF_APPLETALK
Appletalk(DDP)プロトコル
PF_PACKET/AF_PACKET
プライマリパッケージインタフェース
PF_INET/AF_INET
Ipv 4ネットワークプロトコル
PF_INET/AF_INET
Ipv 4ネットワークプロトコル
2.typeのカテゴリ.表を参照:
を選択します.
説明
SOCK_STREAM
双方向連続かつ信頼性の高いデータストリーム、すなわちTCPを提供する
SOCK_DGRAM
不連続で信頼できないパケット接続を使用
SOCK_SEQPACKET
継続的で信頼性の高いパケット接続を提供
SOCK_RAW
元のネットワーク・プロトコル・アクセスの提供
SOCK_RDM
信頼性の高いパケット接続を提供
SOCK_PACKET
ネットワークドライバとの直接通信の提供
3.protocolは、socketで使用されるトランスポートプロトコル番号を指定するために使用されます.通常は0です.
戻り値:
成功するとsocket処理コードが返され、失敗すると-1が返されます.
エラーコード:
1、EPROTONOSUPPORTパラメータdomain指定のタイプはパラメータtypeまたはprotocol指定のプロトコル2、ENFILEコアメモリ不足、新しいsocket構造を確立できない3、EMFILEプロセスファイル表オーバーフロー、新しいsocket 4、EACCESS権限不足、typeまたはprotocol指定のプロトコル5、ENOBUFS/ENOMEMメモリ不足6、EINVALパラメータdomain/type/protocolが不正
2.bind()関数
関数の定義:
成功すると0が返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータsockfd非合法socket処理コード.2、EACCESS権限不足3、ENOTSOCKパラメータsockfdはファイル記述語であり、socketではない.
例:
3.listen()待機接続
関数の定義:
Listen()はSOCK_のみ適用STREAMまたはSOCK_SEQACK ETのsocketタイプ.SOcketがAF_の場合INETはパラメータbacklogの最大値を128に設定ことができる.
パラメータ:
1.パラメータsすなわちsocketfd
2.パラメータbacklogは同時に処理できる最大接続要求を指定し、接続数がこの上限に達するとclient側はECONNREFUSEDのエラーを受け取る.
戻り値:
成功すると0が返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータsockfd非合法socket処理コード2.EACCESSの権限が3.EOPNOTSUPPが指定するsocketはlistenモードをサポートしていない.
例:
4.accept()接続を受け入れる
関数の定義:
まずbind()とlisten()関数で処理する必要があり、接続が入るとaccept()は新しいsocket処理コードを返し、その後のデータ転送と読み取りは新しいsocket処理を経由し、元のパラメータsのsocketはaccept()を引き続き使用して新しい接続要求を受け入れることができる.
接続に成功すると、パラメータaddrが指す構造はシステムによってリモートホストのアドレスデータに埋め込まれ、パラメータaddrlenはscokaddrの構造長である.
戻り値:
成功すると新しいsocket処理コードが返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータs非合法socket処理コード.2、EFAULTパラメータaddrポインタはアクセスできないメモリ空間を指す.3、ENOTSOCKパラメータsはファイル記述語であり、socketではない.4、EOPNOTSUPP指定のソケットがSOCK_ではないSTREAM. 5.EPERMファイアウォールはこの接続を拒否する.6、ENOBUFSシステムのバッファメモリが不足している.7、ENOMEMコアのメモリが不足している.
例:
5.connect()socket接続の確立
関数の定義:
connect()パラメータsockfdのsocketをパラメータserv_に接続するためのaddrが指定したネットワークアドレス.クライアント接続に一般的に使用されます.
戻り値:
成功すると0が返され、失敗すると-1が返されます.
エラーコード:
1、EBADFパラメータsockfd非合法socket処理コード2、EFAULTパラメータserv_addrポインタはアクセスできないメモリ空間3を指し、ENOTSOCKパラメータsockfdはsocketではないファイル記述語である.4、EISCONNパラメータsockfdのsocketは既に結線状態5である、ETIMEDOUTが結線しようとする操作が制限時間を超えても応答しない.6、ENETUNREACHは指定のホストにパケットを転送できない.7、EAFNOSUPPORT sockaddr構造のsa_familyが正しくない.8、EALREADYソケットは遮断不能であり、かつ以前の配線操作がまだ完了していない.
例:
6.recv()受信データ
関数の定義:
recv関数は一般的にブロックされています.しかし、ネットワークが切断されるなどの予期せぬ状況が発生すると、socketは閉じられ、resvはブロックされ続けます.この場合、ブロックされたsocketに対してsetsockoptを使用してsocketのタイムアウトを設定するのが一般的です.
flagsは一般的に0に設定されます.
を選択します.
説明
MSG_OOB
out-of-bandで送出するデータを受信する.
MSG_PEEK
返されたデータはシステム内で削除する、recv()を呼び出すと同じデータ内容が返される.
MSG_WAITALL
エラーや信号が発生しない限り、lenサイズのデータを強制的に受信してから戻る.
MSG_NOSIGNAL
この動作はSIGPIPE信号によって中断する戻り値が成功すると受信した文字数を返し、失敗して-1を返し、エラーの原因はerrnoに格納.
エラーコード:
1.EBADFパラメータsの非合法なsocket処理コード2.EFAULTパラメータにはアクセスできないメモリ領域を指すポインタがある.ENOTSOCKパラメータsはファイル記述語であり、socketではない.4.EINTRは信号によって中断する.EAGAINこの動作はプロセスを遮断するが、パラメータsのsocketは遮断できない6である.ENOBUFSシステムのバッファメモリが不足している.7.ENOMEMコアメモリ不足8.EINVALがシステム呼び出しに伝達するパラメータが正しくない.
例:
7.send()転送データ
関数の定義:
send()は、指定するsocketから相手ホストにデータを転送するために使用される.パラメータsは接続が確立されたsocketである.パラメータmsgは接続しようとするデータの内容を指し、パラメータlenはデータ長である.パラメータflagsは一般的に0に設定されます.
戻り値:
成功すると実際に転送された文字数が返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータsの非合法的なsocket処理コード.2.EFAULTパラメータのポインタがアクセスできないメモリ領域を指す.ENOTSOCKパラメータsはファイル記述語であり、socketではない.4.EINTRは信号によって中断する.5.EAGAINこの操作はプロセスを遮断するが、パラメータsのsocketは遮断できない.6.ENOBUFSシステムのバッファメモリ不足7.ENOMEMコアメモリ不足8.EINVALがシステム呼び出しに伝達するパラメータが正しくない.
例:
8.shutdown()socketを閉じる
関数の定義:
howパラメータ:
how=0は読み出し動作を終了する.how=1転送終了how=2読み出しおよび転送終了
エラーコード:
1、EBADFパラメータsは有効なsocket処理コード2ではなく、ENOTSOCKパラメータsはファイル記述語であり、非socket 3、ENOTCONパラメータsが指定したsocketは接続されていない
例:
サービス側の例
まず、マルチスレッド、マルチユーザ接続をサポートするブロックIOモードのSOCKETの例を見る.なぜIOがブロックされているのか、私の文章を参考にしてください.http://blog.csdn.net/initphp/article/details/42011845
スレッドが使用されているため、例のコンパイル:
gcc main.c -o main -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
//
typedef struct args {
int client_socketfd;
} ARGS;
//
void * recv_msg(void * args) {
ARGS * args_p = (ARGS * ) args;
//
char * msg = "Welcome to My socket";
int size = send(args_p->client_socketfd, msg, strlen(msg), 0);
//
char buf[1024]; //
int len;
while ((len = recv(args_p->client_socketfd, buf, 1024, 0)) > 0) {
buf[len] = '\0';
printf("%s
", buf);
if (send(args_p->client_socketfd, buf, len, 0) < 0) {
perror("write");
}
}
free(args_p); //
shutdown(args_p->client_socketfd, 2); // socketid
}
int server() {
int server_socketfd; // socket
struct sockaddr_in server_addr; //
memset(&server_addr,0,sizeof(server_addr)); // --
server_addr.sin_family = AF_INET; // IP
server_addr.sin_addr.s_addr = INADDR_ANY;// IP --
server_addr.sin_port = htons(8000); //
//
server_socketfd = socket(PF_INET,SOCK_STREAM,0);
if (server_socketfd < 0) {
puts("socket error");
return 0;
}
// IP
if (bind(server_socketfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))<0) {
puts("bind error");
return 0;
}
// , 5
listen(server_socketfd, 1);
//
while (1) {
int client_socketfd;//
struct sockaddr_in client_addr; //
int in_size = sizeof(struct sockaddr_in);
// socket
client_socketfd = accept(server_socketfd, (struct sockaddr *) &client_addr, &in_size); // ,
if (client_socketfd < 0) {
puts("accpet error");
return 0;
}
printf("IP :%s", inet_ntoa(client_addr.sin_addr));
// , , free,
ARGS *args = (ARGS *) malloc(sizeof (ARGS *));
args->client_socketfd = client_socketfd;
pthread_t t1;
int x = pthread_create(&t1, NULL , recv_msg, args); //
if (x != 0) {
puts(" ");
}
}
shutdown(server_socketfd, 2); // socket
}
int main(void) {
server(); // Server
return 0;
}
クライアントの例
クライアントの例を見ることができます.この例は主にsocketによってサービス側に接続され、サービス側にメッセージを送信し、応答を受信する.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
int main() {
int client_fd; // SOCKET
struct sockaddr_in server_addr; //
memset(&server_addr,0,sizeof(server_addr)); // --
server_addr.sin_family=AF_INET; // IP
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");// IP
server_addr.sin_port = htons(8000); //
client_fd = socket(PF_INET, SOCK_STREAM, 0);
if (client_fd < 1) {
puts("client socket error");
return 0;
}
/* , */
int ret = connect(client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if (ret < 0) {
puts("client connect error!");
return 0;
}
char buf[1024];
int len = recv(client_fd, buf, 1024, 0); //
buf[len] = '\0';
puts(buf);
char *x = "Hello World";
send(client_fd, x, strlen(x), 0); //
memset(buf, 0, 1024);
int len2 = recv(client_fd, buf, 1024, 0); //
buf[len2] = '\0';
puts(buf);
shutdown(client_fd,2); // socket
}
共通インタフェース
1.socket()関数
関数の定義:
int socket(int domain, int type, int protocol);
socket関数は、新しいsocketを確立するために使用され、すなわち、システムに登録し、通信ポートを確立することを通知する.パラメータ:
1.domainは、どのアドレスタイプを使用するかを指定します.
プロトコル
説明
PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL
UNIXプロセス通信プロトコル
PF_INET/AF_INET
Ipv 4ネットワークプロトコル
PF_INET6/AF_INET6
Ipv 6ネットワークプロトコル
PF_IPX/AF_IPX IPX-Novell
プロトコル
PF_NETLINK/AF_NETLINK
コアユーザインタフェース装置
PF_X25/AF_X25
ITU-T X.25/ISO-8208プロトコル
PF_AX25/AF_AX25
アマチュア無線AX25プロトコル
PF_ATMPVC/AF_ATMPVC
元ATM PVCsへのアクセス
PF_APPLETALK/AF_APPLETALK
Appletalk(DDP)プロトコル
PF_PACKET/AF_PACKET
プライマリパッケージインタフェース
PF_INET/AF_INET
Ipv 4ネットワークプロトコル
PF_INET/AF_INET
Ipv 4ネットワークプロトコル
2.typeのカテゴリ.表を参照:
を選択します.
説明
SOCK_STREAM
双方向連続かつ信頼性の高いデータストリーム、すなわちTCPを提供する
SOCK_DGRAM
不連続で信頼できないパケット接続を使用
SOCK_SEQPACKET
継続的で信頼性の高いパケット接続を提供
SOCK_RAW
元のネットワーク・プロトコル・アクセスの提供
SOCK_RDM
信頼性の高いパケット接続を提供
SOCK_PACKET
ネットワークドライバとの直接通信の提供
3.protocolは、socketで使用されるトランスポートプロトコル番号を指定するために使用されます.通常は0です.
戻り値:
成功するとsocket処理コードが返され、失敗すると-1が返されます.
エラーコード:
1、EPROTONOSUPPORTパラメータdomain指定のタイプはパラメータtypeまたはprotocol指定のプロトコル2、ENFILEコアメモリ不足、新しいsocket構造を確立できない3、EMFILEプロセスファイル表オーバーフロー、新しいsocket 4、EACCESS権限不足、typeまたはprotocol指定のプロトコル5、ENOBUFS/ENOMEMメモリ不足6、EINVALパラメータdomain/type/protocolが不正
2.bind()関数
関数の定義:
int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
bind()は、パラメータsockfdのsocketの名前を設定するために使用される.成功すると0が返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータsockfd非合法socket処理コード.2、EACCESS権限不足3、ENOTSOCKパラメータsockfdはファイル記述語であり、socketではない.
例:
// IP
if (bind(server_socketfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))<0) {
puts("bind error");
return 0;
}
3.listen()待機接続
関数の定義:
int listen(int s, int backlog);
listen()は、パラメータsのsocket接続を待つために使用される.Listen()はSOCK_のみ適用STREAMまたはSOCK_SEQACK ETのsocketタイプ.SOcketがAF_の場合INETはパラメータbacklogの最大値を128に設定ことができる.
パラメータ:
1.パラメータsすなわちsocketfd
2.パラメータbacklogは同時に処理できる最大接続要求を指定し、接続数がこの上限に達するとclient側はECONNREFUSEDのエラーを受け取る.
戻り値:
成功すると0が返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータsockfd非合法socket処理コード2.EACCESSの権限が3.EOPNOTSUPPが指定するsocketはlistenモードをサポートしていない.
例:
// , 5
listen(server_socketfd, 1);
4.accept()接続を受け入れる
関数の定義:
int accept(int s, struct sockaddr * addr, int * addrlen);
accept()は、パラメータsのsocket接続を受け入れるために用いる.パラメータsのsocketまずbind()とlisten()関数で処理する必要があり、接続が入るとaccept()は新しいsocket処理コードを返し、その後のデータ転送と読み取りは新しいsocket処理を経由し、元のパラメータsのsocketはaccept()を引き続き使用して新しい接続要求を受け入れることができる.
接続に成功すると、パラメータaddrが指す構造はシステムによってリモートホストのアドレスデータに埋め込まれ、パラメータaddrlenはscokaddrの構造長である.
戻り値:
成功すると新しいsocket処理コードが返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータs非合法socket処理コード.2、EFAULTパラメータaddrポインタはアクセスできないメモリ空間を指す.3、ENOTSOCKパラメータsはファイル記述語であり、socketではない.4、EOPNOTSUPP指定のソケットがSOCK_ではないSTREAM. 5.EPERMファイアウォールはこの接続を拒否する.6、ENOBUFSシステムのバッファメモリが不足している.7、ENOMEMコアのメモリが不足している.
例:
int client_socketfd;//
struct sockaddr_in client_addr; //
int in_size = sizeof(struct sockaddr_in);
// socket
client_socketfd = accept(server_socketfd, (struct sockaddr *) &client_addr, &in_size); // ,
5.connect()socket接続の確立
関数の定義:
int connect(int sockfd, struct sockaddr * serv_addr, int addrlen);
connect()パラメータsockfdのsocketをパラメータserv_に接続するためのaddrが指定したネットワークアドレス.クライアント接続に一般的に使用されます.
戻り値:
成功すると0が返され、失敗すると-1が返されます.
エラーコード:
1、EBADFパラメータsockfd非合法socket処理コード2、EFAULTパラメータserv_addrポインタはアクセスできないメモリ空間3を指し、ENOTSOCKパラメータsockfdはsocketではないファイル記述語である.4、EISCONNパラメータsockfdのsocketは既に結線状態5である、ETIMEDOUTが結線しようとする操作が制限時間を超えても応答しない.6、ENETUNREACHは指定のホストにパケットを転送できない.7、EAFNOSUPPORT sockaddr構造のsa_familyが正しくない.8、EALREADYソケットは遮断不能であり、かつ以前の配線操作がまだ完了していない.
例:
/* , */
int ret = connect(client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if (ret < 0) {
puts("client connect error!");
return 0;
}
6.recv()受信データ
関数の定義:
int recv(int s, void *buf, int len, unsigned int flags);
recv()は、遠隔ホストから指定されたsocketを介して送信されたデータを受信し、パラメータbufによって指し示すメモリ空間にデータを格納するために使用され、パラメータlenは受信可能なデータの最大長である.recv関数は一般的にブロックされています.しかし、ネットワークが切断されるなどの予期せぬ状況が発生すると、socketは閉じられ、resvはブロックされ続けます.この場合、ブロックされたsocketに対してsetsockoptを使用してsocketのタイムアウトを設定するのが一般的です.
flagsは一般的に0に設定されます.
を選択します.
説明
MSG_OOB
out-of-bandで送出するデータを受信する.
MSG_PEEK
返されたデータはシステム内で削除する、recv()を呼び出すと同じデータ内容が返される.
MSG_WAITALL
エラーや信号が発生しない限り、lenサイズのデータを強制的に受信してから戻る.
MSG_NOSIGNAL
この動作はSIGPIPE信号によって中断する戻り値が成功すると受信した文字数を返し、失敗して-1を返し、エラーの原因はerrnoに格納.
エラーコード:
1.EBADFパラメータsの非合法なsocket処理コード2.EFAULTパラメータにはアクセスできないメモリ領域を指すポインタがある.ENOTSOCKパラメータsはファイル記述語であり、socketではない.4.EINTRは信号によって中断する.EAGAINこの動作はプロセスを遮断するが、パラメータsのsocketは遮断できない6である.ENOBUFSシステムのバッファメモリが不足している.7.ENOMEMコアメモリ不足8.EINVALがシステム呼び出しに伝達するパラメータが正しくない.
例:
//
char buf[1024]; //
int len;
while ((len = recv(args_p->client_socketfd, buf, 1024, 0)) > 0) {
buf[len] = '\0';
printf("%s
", buf);
if (send(args_p->client_socketfd, buf, len, 0) < 0) {
perror("write");
}
}
7.send()転送データ
関数の定義:
int send(int s, const void * msg, int len, unsigned int falgs);
send()は、指定するsocketから相手ホストにデータを転送するために使用される.パラメータsは接続が確立されたsocketである.パラメータmsgは接続しようとするデータの内容を指し、パラメータlenはデータ長である.パラメータflagsは一般的に0に設定されます.
戻り値:
成功すると実際に転送された文字数が返され、失敗すると-1が返されます.
エラーコード:
1.EBADFパラメータsの非合法的なsocket処理コード.2.EFAULTパラメータのポインタがアクセスできないメモリ領域を指す.ENOTSOCKパラメータsはファイル記述語であり、socketではない.4.EINTRは信号によって中断する.5.EAGAINこの操作はプロセスを遮断するが、パラメータsのsocketは遮断できない.6.ENOBUFSシステムのバッファメモリ不足7.ENOMEMコアメモリ不足8.EINVALがシステム呼び出しに伝達するパラメータが正しくない.
例:
//
char * msg = "Welcome to My socket";
int size = send(args_p->client_socketfd, msg, strlen(msg), 0);
8.shutdown()socketを閉じる
関数の定義:
int shutdown(int s, int how);
shutdown()は、パラメータsによって指定されたsocket配線を終了するために使用される.howパラメータ:
how=0は読み出し動作を終了する.how=1転送終了how=2読み出しおよび転送終了
エラーコード:
1、EBADFパラメータsは有効なsocket処理コード2ではなく、ENOTSOCKパラメータsはファイル記述語であり、非socket 3、ENOTCONパラメータsが指定したsocketは接続されていない
例:
shutdown(server_socketfd, 2); // socket