Linux Network - yusukew62/docs GitHub Wiki
sample code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
int main()
{
int sock[10000];
int i,j;
scanf("%d", &j);
for(i=1; i<1025; i++){
sock[i] = socket(AF_INET, SOCK_STREAM, 0);
printf("%d: %d\n", i, sock[i]);
if(sock[i]<0){
printf("%d:%s\n", errno, strerror(errno));
}
}
scanf("%d", &j);
return 0;
}pidを確認
# ps -ef| grep -v grep | grep a.out
root 21364 1428 0 09:47 pts/0 00:00:00 ./a.out
pidのprocへ移動
# cd /proc/21364/fd
上記のワンライナー
# aout=$(ps -ef| grep -v grep | grep a.out| awk '{print $2}'); cd /proc/${aout}
ソケット作成前のFDは0-2の3つ(0:stdin, 1:stdout, 2:stderr)
# ll
合計 0
lrwx------. 1 root root 64 3月 4 09:49 2018 0 -> /dev/pts/0
lrwx------. 1 root root 64 3月 4 09:49 2018 1 -> /dev/pts/0
lrwx------. 1 root root 64 3月 4 09:47 2018 2 -> /dev/pts/0
ソケットはFD番号3から作成され、標準では1023までのため1024を作成する際にエラーが出る
# ./a.out
1: 3
2: 4
3: 5
(省略)
1020: 1022
1021: 1023
1022: -1
24:Too many open files
1023: -1
24:Too many open files
作成されたソケットのファイルを確認
# ll | grep 1023
lrwx------. 1 root root 64 3月 4 09:49 2018 1023 -> socket:[64416]
FDの1023はシンボリックリンク
# stat 1023
File: `1023' -> `socket:[64416]'
Size: 64 Blocks: 0 IO Block: 1024 シンボリックリンク
Device: 3h/3d Inode: 65446 Links: 1
Access: (0700/lrwx------) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-03-04 09:49:28.151503039 +0900
Modify: 2018-03-04 09:49:28.134503015 +0900
Change: 2018-03-04 09:49:28.134503015 +0900
実体はソケットファイル
# stat -L 1023
File: `1023'
Size: 0 Blocks: 0 IO Block: 4096 ソケット
Device: 6h/6d Inode: 64416 Links: 1
Access: (0777/srwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1970-01-01 09:00:00.000000000 +0900
Modify: 1970-01-01 09:00:00.000000000 +0900
Change: 1970-01-01 09:00:00.000000000 +0900
straceでシステムコールを確認すると下記のようになっている
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 1022
write(1, "1020: 1022\n", 111020: 1022
) = 11
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 1023
write(1, "1021: 1023\n", 111021: 1023
) = 11
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = -1 EMFILE (Too many open files)
write(1, "1022: -1\n", 91022: -1
) = 9
write(1, "24:Too many open files\n", 2324:Too many open files
) = 23
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = -1 EMFILE (Too many open files)
write(1, "1023: -1\n", 91023: -1
) = 9sample code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
int main()
{
int sock0;
int len;
int sock;
struct sockaddr_in server;
struct sockaddr_in client;
sock0=socket(AF_INET, SOCK_STREAM, 0);
if(sock0 < 0){
perror("socket");
}
server.sin_family = AF_INET;
server.sin_port = htons(12345);
server.sin_addr.s_addr = INADDR_ANY;
if(bind(sock0, (struct sockaddr *) &server, sizeof(server))!=0) {
perror("bind");
}
if(listen(sock0, 5)!=0) {
perror("listen");
}
len = sizeof(client);
sock = accept(sock0, (struct sockaddr *) &client, &len);
if(sock < 0) {
perror("socket");
}
write(sock, "Hello", 5);
close(sock);
close(sock0);
return 0;
}sample code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
int main()
{
int sock;
struct sockaddr_in client;
char buf[32];
int n;
sock=socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0) {
perror("socket");
}
client.sin_family = AF_INET;
client.sin_port = htons(12345);
client.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(sock, (struct sockaddr *) &client, sizeof(client))<0) {
perror("connect");
}
memset(buf, 0, sizeof(buf));
n = read(sock, buf, sizeof(buf));
printf("%d, %s\n", n, buf);
close(sock);
return 0;
}クライアント側のシステムコール
# strace ./cl
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
read(3, "Hello", 32) = 5
close(3) = 0
サーバ側のシステムコール
# strace ./sv
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 5) = 0
accept(3, {sa_family=AF_INET, sin_port=htons(37286), sin_addr=inet_addr("127.0.0.1")}, [16]) = 4
write(4, "Hello", 5) = 5
close(4) = 0
close(3) = 0
クライアント接続前はLISTEN状態
tcp 0 0 0.0.0.0:12345 0.0.0.0:* LISTEN 0 154500
tcp 0 0 127.0.0.1:37290 127.0.0.1:12345 ESTABLISHED 0 154584
tcp 0 0 127.0.0.1:12345 127.0.0.1:37290 ESTABLISHED 0 154501
サーバ側FD
lrwx------. 1 root root 64 3月 4 14:22 2018 3 -> socket:[154500]
lrwx------. 1 root root 64 3月 4 14:22 2018 4 -> socket:[154501]
クライアント接続後はTIME_WAIT状態
tcp 0 0 127.0.0.1:37290 127.0.0.1:12345 TIME_WAIT 0 0
備考
backlogは保留中の接続のキューの最大長を指定する
int listen(int sockfd, int backlog);
不完全なソケットのキューの最大長は /proc/sys/net/ipv4/tcp_max_syn_backlog を用いて設定できる
# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
512
backlog 引き数が /proc/sys/net/core/somaxconn の値よりも大きければ、 backlog の値は暗黙のうちにこの値に切り詰められる
# cat /proc/sys/net/core/somaxconn
128
以下のヘッダファイルに定義されている
/usr/include/linux/in.h
sockaddr_in構造体
/* Structure describing an Internet (IP) socket address. */
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
struct sockaddr_in {
sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};in_addr構造体
/* Internet address. */
struct in_addr {
__be32 s_addr;
};INADDR_ANY
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000)listen()が含まれているヘッダファイル
/usr/include/sys/socket.h
listen()の中身
extern int listen (int __fd, int __n) __THROW;
/* Await a connection on socket FD.
When a connection arrives, open a new socket to communicate with it,
set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
peer and *ADDR_LEN to the address's actual length, and return the
new socket's descriptor, or -1 for errors.
This function is a cancellation point and therefore not marked with
__THROW. */