setsockopt(2)ã§SO_SNDTIMEO, SO_RCVTIMEOãæå®ã§ããªã?
å¿ããããã«ä½¿ãã©ãããåºã¦ããã½ã±ããã¾ããã®è©±ï¼socketã®è¨å®ã«ã¯setsockopt(2)ã§ããããããã®ã ããã©ï¼ä»åã¯ä»¥ä¸ã®2ã±ã¼ã¹ã®ã¿ã¤ã ã¢ã¦ãè¨å®ã«ææ¦ãã¦ï¼ãã¼ãã¶ãã¾ããããªãã£ãããã©ï¼ãããã試è¡é¯èª¤ãããã失æè¨äºã«ãã¦ã¿ãï¼
- (1) æ¥ç¶å ãã¹ãã«å¯¾ãã¦connect(2)失æã®ã¿ã¤ã ã¢ã¦ããæå®ãããï¼
- (2) æ¥ç¶ããç¶æ ã§æ¥ç¶å ãã¹ãããã¦ã³ããã¨ããªã©ï¼read, writeã®å¿çãªãã®ã¿ã¤ã ã¢ã¦ããæå®ãããï¼
ä»åã¯ï¼ä»¥ä¸ã®ç°å¢ã§å®é¨ããï¼ãµãã¤ã®ç°å¢ã§æåãéã£ãããï¼ã¾ãæ³£ããããªãï¼
(1) connectã¿ã¤ã ã¢ã¦ãã®è¨å®
ã¾ã(1)ããï¼ä»¥ä¸ã®è¨äºãè¦ãã¨ï¼ã©ãããsetsockopt(2)ã§SO_SNDTIMEOãè¨å®ããã°ããããï¼
ãªãã ï¼ç°¡åãããªããã¨ï¼ã¨ã©ã¼å¦çã®ãªãæ¸ãæ®´ãã½ã¼ã¹ãæ¸ãã¦ã¿ãï¼
- connect.c
// // % echo "fugafuga" | nc -l -p 4649 // #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main (int argc, char *argv[]) { int sock = socket( PF_INET, SOCK_STREAM, 0 ); struct timeval send_tv; send_tv.tv_sec = 1; send_tv.tv_usec = 0; setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, &send_tv, sizeof(send_tv) ); struct timeval recv_tv; recv_tv.tv_sec = 5; recv_tv.tv_sec = 0; // ã³ã¡ã³ãã¢ã¦ãããã¨1ç§ã§TIMEOUTãããªã setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &recv_tv, sizeof(recv_tv) ); struct sockaddr_in sa; memset( &sa, 0, sizeof( sa ) ); // sa.sin_len = sizeof( sa ); sa.sin_family = AF_INET; sa.sin_port = htons( 4649 ); sa.sin_addr.s_addr = inet_addr( "127.0.0.1" ); connect( sock, (struct sockaddr *)&sa, sizeof( sa ) ); char buff[ 1024 ]; read( sock, buff, 1024 ); printf("%s\n", buff ); return 0; }
ã¡ããã¨ã¤ãªãã£ããã©ããã確èªããããã«ï¼netcatã使ã£ã¦4649ãã¼ããlistenããï¼
% echo "fugafuga" | nc -l -p 4649
å¥ã®ç«¯æ«ãã以ä¸ãå®è¡
% gcc -o connect connect.c % ./connect fugafuga
ã¡ããã¨4649ãã¼ãã«æ¥ç¶ãã¦ã¡ãã»ã¼ã¸ãåãåã£ããã¨ããããï¼
ãã¦çä¼¼çã«ãã¹ãããã¦ã³ãã¦ãããã¨ãåç¾ããããï¼iptablesã«ãããã±ãããã£ã«ã¿ãªã³ã°ãè¡ãï¼
# iptables -A INPUT -p tcp -s 127.0.0.1 --dport 4649 -j DROP (è¨å®è§£é¤ã¯ # iptables -D INPUT -p tcp -s 127.0.0.1 --dport 4649 -j DROP)
ããã§ï¼localhostããæ¥ã4649ãã¼ãå®ã®ãã±ããã¯dropãããï¼åã³connectãå®è¡
% ./connect (Xç§çµé) %
(A)ã§ã¯ï¼SO_SNDTIMEOã®æéã§ã¿ã¤ã ã¢ã¦ãããï¼ãã ãï¼SO_RCVTIMEOãè¨å®ããªãã¨æå®ããæéã§ã¿ã¤ã ã¢ã¦ãããªãã£ãï¼(è¬ã®æå)
(B)ã§ã¯ï¼SO_SNDTIMEOï¼SO_RCVTIMEOãããã®æéã¨ãé¢ä¿ã®ãªã21ç§ã§ã¿ã¤ã ã¢ã¦ãããï¼
Linuxã®ã³ãã¯ãã¿ã¤ã ã¢ã¦ãã¯ï¼æ示çã«ã¯æå®ã§ããªããã®ãããï¼
(2) readã¿ã¤ã ã¢ã¦ãã®è¨å®
ä»åº¦ã¯ãæ¥ç¶ã¯æåããã®ã ããã©ï¼readã®ã¿ã¤ãã³ã°ã§ãã¹ãã®å¿çããªããªã£ãæã«ã¿ã¤ã ã¢ã¦ãããæéããæå®ãããã¨ããã±ã¼ã¹ï¼ãã®ã±ã¼ã¹ã ã¨ä¸è¨ã®netcatã使ã£ããµã¼ãã ã¨æ¥ç¶ããã¿ã¤ãã³ã°ã§ã¯ã©ã¤ã¢ã³ãã®readãããã¡ã«å ¥ã£ã¦ãã¾ãã®ã§ï¼scanf()ã§å¾ ã¡æéãä½ãã¨ãããã¯ãæ¹æ³ã§åç¾ãã¦ã¿ãï¼
å®é¨æé
- serverãèµ·å
- clientãèµ·åï¼scanf()ã§å¾ ã¡ãçºç
- iptables ã§ãã±ãããã£ã«ã¿ãã
- clientã®scanf()ãå®è¡ï¼readãã§ããªãç¶æ ã«é¥ã
ã¨ããæãï¼ã½ã¼ã¹ã³ã¼ãã¯ä»¥ä¸ã®ã¨ããï¼
- server.c
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main (int argc, char *argv[]) { int sock = socket( PF_INET, SOCK_STREAM, 0 ); struct timeval send_tv; send_tv.tv_sec = 1; send_tv.tv_usec = 0; // æå³ãªã? setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, &send_tv, sizeof(send_tv) ); struct timeval recv_tv; recv_tv.tv_sec = 5; recv_tv.tv_sec = 0; // æå³ãªã? setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &recv_tv, sizeof(recv_tv) ); struct sockaddr_in sa; memset( &sa, 0, sizeof( sa ) ); // sa.sin_len = sizeof( sa ); sa.sin_family = AF_INET; sa.sin_port = htons( 4649 ); sa.sin_addr.s_addr = inet_addr( "127.0.0.1" ); // localhostããã®ã¿ struct sockaddr_in client; int client_len = sizeof( client ); bind( sock, (struct sockaddr *)&sa, sizeof( sa ) ); listen( sock, 1 ); int client_sock = accept( sock, (struct sockaddr *)&client, (socklen_t *)&client_len ); char buff[ 1024 ]; read( client_sock, buff, 1024 ); printf("%s\n", buff ); char *msg = "bye"; write( client_sock, msg, strlen(msg) + 1 ); return 0; }
- client.c
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main (int argc, char *argv[]) { int sock = socket( PF_INET, SOCK_STREAM, 0 ); struct timeval send_tv; send_tv.tv_sec = 2; send_tv.tv_usec = 0; setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, &send_tv, sizeof(send_tv) ); struct timeval recv_tv; recv_tv.tv_sec = 5; recv_tv.tv_sec = 0; setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &recv_tv, sizeof(recv_tv) ); struct sockaddr_in sa; memset( &sa, 0, sizeof( sa ) ); // sa.sin_len = sizeof( sa ); sa.sin_family = AF_INET; sa.sin_port = htons( 4649 ); sa.sin_addr.s_addr = inet_addr( "127.0.0.1" ); connect( sock, (struct sockaddr *)&sa, sizeof( sa ) ); char input[ 1024 ]; printf("Input message> "); scanf("%s", input); write( sock, input, strlen( input ) + 1 ); char buff[ 1024 ]; read( sock, buff, 1024 ); printf("%s\n", buff ); return 0; }
å®é¨ãã¦ã¿ãï¼
端æ«1ã§ãµã¼ããèµ·å
% ./server
端æ«2ã§ã¯ã©ã¤ã¢ã³ããèµ·å
% ./client Input message>
ãã¾ã ! iptablesãè¨å®
# iptables -A INPUT -p tcp -s 127.0.0.1 --dport 4649 -j DROP
ãã¾ã ! clientã§ã¡ãã»ã¼ã¸ãå ¥å
% ./client Input message> hoge
ããã¦è¨å®ããSO_RCVTIMEOéãã«åãã確èªï¼ã¡ã¼ãï¼5ç§ã§ã1ç§ã§ãè¿ã£ã¦ãã¾ããã§ããï¼ãªãã§ã¼??
ã¨ããããã§ï¼ä»åã¯ç²ããã®ã§writeã®æ¹ã¯ç¢ºèªãã¦ããªãããã©ï¼ããããåããããªæåã«ãªãã¨æãããï¼ãã¼ãï¼
ã©ããã®ãã¼ã¸ã§SO_RCVTIMEOã®å®è£ ã¯POSIXã§ã¯ããã¾ã§æ¨å¥¨ã«ãªã£ã¦ããã®ã§ç°å¢ã«ãã£ã¦ã¯å®è£ ããã¦ãªããï¼Linuxã§ã¯å®è£ ããã¦ãªããã¼ã¨ããæ¸ãè¾¼ã¿ãè¦ãã®ã ããã©ï¼è¦ã¤ãããªããªã£ã¦ããï¼ï¼ï¼ã¾ã¼ãã?