Í¼ÎªÃæÏòÁ¬½ÓµÄSocketͨÐŵÄË«·½Ö´Ðк¯ÊýÁ÷³Ì¡£Ê¹ÓÃTCPÐÒéµÄͨÐÅË«·½ÊµÏÖÊý¾ÝͨÐŵĻù±¾Á÷³ÌÈçÏÂ

½¨Á¢Á¬½ÓµÄ²½Öè
1¡¢Ê×ÏÈ·þÎñÆ÷¶ËÐèÒªÒÔϹ¤×÷£º
£¨1£©µ÷ÓÃsocket£¨£©º¯Êý£¬½¨Á¢Socket¶ÔÏó£¬Ö¸¶¨Í¨ÐÅÐÒé¡£
£¨2£©µ÷ÓÃbind()º¯Êý£¬½«´´½¨µÄSocket¶ÔÏóÓ뵱ǰÖ÷»úµÄijһ¸öIPµØÖ·ºÍTCP¶Ë¿Ú°ó¶¨¡£
£¨3£©µ÷ÓÃlisten£¨£©º¯Êý¡£Ê¹Socket¶ÔÏó´¦ÓÚ¼àÌý״̬£¬²¢ÉèÖüàÌý¶ÓÁдóС¡£
2¡¢¿Í»§¶ËµÄ×¼±¸¹¤×÷£º
£¨1£©µ÷ÓÃsocketº¯Êý£¬½¨Á¢Socket¶ÔÏó£¬Ö¸¶¨Óë·þÎñÆ÷¶ËÏàͬµÄͨÐÅÐÒé¡£
£¨2£©Ó¦ÓóÌÐò¿ÉÒÔµ÷ÓÃbind£¨£©º¯ÊýΪÆä°ó¶¨IPµØÖ·ºÍ¶Ë¿Ú£¬´Ë¹¤×÷Ò²¿É½»¸øTCP/IPÍê³É¡£
3¡¢½¨Á¢Í¨ÐÅÁ¬½Ó
£¨1£©¿Í»§¶Ëµ÷ÓÃconnect()º¯Êý£¬Ïò·þÎñÆ÷¶Ë·¢³öÁ¬½ÓÇëÇó¡£
£¨2£©·þÎñ¶Ë¼àÌýµ½¸ÃÇëÇ󣬵÷ÓÃaccept£¨£©º¯Êý½ÓÊÜÇëÇ󣬽¨Á¢Á¬½Ó£¬²¢·µ»ØÒ»¸öеÄSocketÎļþÃèÊö·ûÒÔרÃÅ´¦Àí¸ÃÁ¬½Ó¡£
4¡¢Í¨ÐÅË«·½·¢ËÍ/½ÓÊÕÊý¾Ý
£¨1£©·þÎñÆ÷¶ËºÍ¿Í»§¶Ë·Ö±ðµ÷ÓÃwrite£¨£©»òsend£¨£©º¯Êý·¢ËÍÊý¾Ýread»òrecvº¯Êý½ÓÊÕÊý¾Ý¡£
£¨2£©Í¨ÐÅÍê³Éºó£¬Í¨ÐÅË«·½¶¼ÐèÒªµ÷ÓÃclose»òshutdownÀ´¹Ø±ÕSocket¡£
ÊìϤÉÏÊöÁ÷³Ìºó,ÍøÂç±à³ÌµÄÖØµã¾ÍÔÚÓÚÓ¦Óò㿪·¢µÄÐÒéʵÏÖÉÏÁË.
BSD SocketÍøÂ·±à³ÌAPI
½¨Á¢Ì×½Ó×Ö,´´½¨socket¶ÔÏó
ʹÓÃsocketº¯Êý´´½¨socket,ÉùÃ÷ÈçÏÂ:
<span style="font-family: Arial; font-size: 14px;">/* Create a new socket of type TYPE in domain DOMAIN, using protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. R</span><span style="font-family:SimSun;font-size:12px;">eturns a file descriptor for the new socket, or -1 for errors. */ extern int socket (int __domain, int __type, int __protocol) __THROW;</span> |
socket()´ò¿ªÒ»¸öÍøÂçͨѶ¶Ë¿Ú£¬Èç¹û³É¹¦µÄ»°£¬¾ÍÏñopen()Ò»Ñù·µ»ØÒ»¸öÎļþÃèÊö·û£¬Ó¦ÓóÌÐò¿ÉÒÔÏñ¶ÁдÎļþÒ»ÑùÓÃread/writeÔÚÍøÂçÉÏÊÕ·¢Êý¾Ý£¬Èç¹ûsocket()µ÷Óóö´íÔò·µ»Ø-1¡£¶ÔÓÚIPv4£¬family²ÎÊýÖ¸¶¨ÎªAF_INET¡£¶ÔÓÚTCPÐÒ飬type²ÎÊýÖ¸¶¨ÎªSOCK_STREAM£¬±íÊ¾ÃæÏòÁ÷µÄ´«ÊäÐÒé¡£Èç¹ûÊÇUDPÐÒ飬Ôòtype²ÎÊýÖ¸¶¨ÎªSOCK_DGRAM£¬±íÊ¾ÃæÏòÊý¾Ý±¨µÄ´«ÊäÐÒé¡£protocol²ÎÊýµÄ½éÉÜ´ÓÂÔ£¬Ö¸¶¨Îª0¼´¿É¡£
µÚÒ»¸ö²ÎÊýÓÃÀ´Ö¸Ã÷socket¶ÔÏóËùʹÓõĵØÖ·´Ø»òÐÒé´Ø,¼´ÊǴ˶ÔÏóʹÓõÄÐÒéÀàÐÍ,ÐÒé´ØµÄºê¶¨ÒåÈçÏÂ:ϵͳԴÎļþ/bit/socket.h
<span style="font-family:SimSun;font-size:12px;">/* Protocol families. */ #define PF_UNSPEC 0 /* Unspecified. */ //䶨Òå #define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ // ±¾µØÍ¨ÐÅ #define PF_UNIX PF_LOCAL /* POSIX name for PF_LOCAL. */ #define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ #define PF_INET 2 /* IP protocol family. */ // IPv4 #define PF_AX25 3 /* Amateur Radio AX.25. */ #define PF_IPX 4 /* Novell Internet Protocol. */ #define PF_INET6 10 /* IP version 6. */ // IPv6</span> |
µØÖ·´ØÊÇÐÒé´ØµÄÖØ¶¨Òå:
<span style="font-family:SimSun;font-size:12px;">/* Address families. */ #define AF_UNSPEC PF_UNSPEC #define AF_LOCAL PF_LOCAL #define AF_UNIX PF_UNIX #define AF_FILE PF_FILE #define AF_INET PF_INET #define AF_AX25 PF_AX25 #define AF_IPX PF_IPX</span> |
µÚ¶þ¸ö²ÎÊýÊÇsocketµÄÀàÐÍ,ϵͳµÄ¶¨ÒåÈçÏÂ:
<span style="font-family:SimSun;font-size:12px;"> 41: /* Types of sockets. */ 42: enum __socket_type 43: { 44: SOCK_STREAM = 1, /* Sequenced, reliable, connection-based 45: byte streams. */ 46: #define SOCK_STREAM SOCK_STREAM 47: SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams 48: of fixed maximum length. */ 49: #define SOCK_DGRAM SOCK_DGRAM 50: SOCK_RAW = 3, /* Raw protocol interface. */ 51: #define SOCK_RAW SOCK_RAW 52: SOCK_RDM = 4, /* Reliably-delivered messages. */ 53: #define SOCK_RDM SOCK_RDM 54: SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, 55: datagrams of fixed maximum length. */ 56: #define SOCK_SEQPACKET SOCK_SEQPACKET 57: SOCK_PACKET = 10 /* Linux specific way of getting packets 58: at the dev level. For writing rarp and 59: other similar things on the user level. */ 60: #define SOCK_PACKET SOCK_PACKET 61: };</span> |
ÈçÉÏÃæµÄ´úÂëËùʾ,ÓÐÁùÖÖsocketÀàÐÍ,×î»ù±¾µÄÀàÐÍÎ»ÃæÏòÁ¬½ÓµÄÊý¾ÝÁ÷·½Ê½ºÍÃæÏòÎÞÁ¬½ÓµÄÊý¾Ý±¨·½Ê½.µÚÈý¸ö²ÎÊý±íʾʹÓÃÄÄÒ»¸öÐÒé,ÉèÖÃΪ0Ôòϵͳ×Ô¶¯Ñ¡Ôñ.
LinuxÔÚÀûÓÃsocket()ϵͳµ÷Óý¨Á¢ÐµÄÌ×½Ó×Öʱ£¬ÐèÒª´«µÝÌ×½Ó×ֵĵØÖ·×å±êʶ·û¡¢Ì×½Ó×ÖÀàÐÍÒÔ¼°ÐÒé,Æäº¯Êý¶¨ÒåÓÚnet/socket.cÖУº
<span style="font-family:SimSun;font-size:12px;">asmlinkagelong sys_socket(int family, int type, int protocol) { int retval; struct socket *sock; retval = sock_create(family, type, protocol,&sock); if (retval < 0) goto out; retval = sock_map_fd(sock); if (retval < 0) goto out_release; out: /* It may be already another descriptor 8) Not kernel problem. */ return retval; out_release: sock_release(sock); return retval; }</span> |
ʵ¼ÊÉÏ£¬Ì×½Ó×Ö¶ÔÓÚÓû§³ÌÐò¶øÑÔ¾ÍÊÇÌØÊâµÄÒÑ´ò¿ªµÄÎļþ¡£ÄÚºËÖÐΪÌ×½Ó×Ö¶¨ÒåÁËÒ»ÖÖÌØÊâµÄÎļþÀàÐÍ£¬ÐγÉÒ»ÖÖÌØÊâµÄÎļþϵͳsockfs£¬Æä¶¨ÒåÓÚnet/socket.c£º
<span style="font-family:SimSun;font-size:12px;"> static struct vfsmount *sock_mnt; static DECLARE_FSTYPE(sock_fs_type, "sockfs",sockfs_read_super, FS_NOMOUNT);</span> |
ÔÚϵͳ³õʼ»¯Ê±£¬ÒªÍ¨¹ýkern_mount()°²×°Õâ¸öÎļþϵͳ¡£°²×°Ê±Óиö×÷ΪÁ¬½Ó¼þµÄvfsmountÊý¾Ý½á¹¹£¬Õâ¸ö½á¹¹µÄµØÖ·¾Í±£´æÔÚÒ»¸öÈ«¾ÖµÄÖ¸Õësock_mntÖС£Ëùν´´½¨Ò»¸öÌ×½Ó×Ö£¬¾ÍÊÇÔÚsockfsÎļþϵͳÖд´½¨Ò»¸öÌØÊâÎļþ£¬»òÕß˵һ¸ö½Úµã£¬²¢½¨Á¢ÆðΪʵÏÖÌ×½Ó×Ö¹¦ÄÜËùÐèµÄÒ»ÕûÌ×Êý¾Ý½á¹¹¡£ËùÒÔ£¬º¯Êýsock_create()Ê×ÏÈÊǽ¨Á¢Ò»¸ösocketÊý¾Ý½á¹¹£¬È»ºó½«Æä¡°Ó³É䡱µ½Ò»¸öÒÑ´ò¿ªµÄÎļþÖУ¬½øÐÐsocket½á¹¹ºÍsock½á¹¹µÄ·ÖÅäºÍ³õʼ»¯¡£
д´½¨µÄ BSD socket Êý¾Ý½á¹¹°üº¬ÓÐÖ¸ÏòµØÖ·×åרÓеÄÌ×½Ó×ÖÀý³ÌµÄÖ¸Õ룬ÕâÒ»Ö¸Õëʵ¼Ê¾ÍÊÇproto_ops
Êý¾Ý½á¹¹µÄµØÖ·¡£
BSD Ì×½Ó×ÖµÄÌ×½Ó×ÖÀàÐÍÉèÖÃΪËùÇëÇóµÄ SOCK_STREAM »ò SOCK_DGRAM
µÈ¡£È»ºó£¬ÄÚºËÀûÓà proto_ops Êý¾Ý½á¹¹ÖеÄÐÅÏ¢µ÷ÓõØÖ·×åרÓеĴ´½¨Àý³Ì¡£
Ö®ºó£¬Äں˴ӵ±Ç°½ø³ÌµÄ fd ÏòÁ¿ÖзÖÅä¿ÕÏеÄÎļþÃèÊö·û£¬¸ÃÃèÊö·ûÖ¸ÏòµÄ
file Êý¾Ý½á¹¹±»³õʼ»¯¡£³õʼ»¯¹ý³Ì°üÀ¨½«Îļþ²Ù×÷¼¯Ö¸ÕëÖ¸ÏòÓÉ BSD Ì×½Ó×Ö½Ó¿ÚÖ§³ÖµÄ BSD Îļþ²Ù×÷¼¯¡£ËùÓÐËæºóµÄÌ×½Ó×Ö£¨Îļþ£©²Ù×÷¶¼½«¶¨Ïòµ½¸ÃÌ×½Ó×Ö½Ó¿Ú£¬¶øÌ×½Ó×Ö½Ó¿ÚÔò»á½øÒ»²½µ÷ÓõØÖ·×åµÄ²Ù×÷Àý³Ì£¬´Ó¶ø½«²Ù×÷´«µÝµ½µ×²ãµØÖ·×å,Èçͼ12.10Ëùʾ¡£
ʵ¼ÊÉÏ£¬socket½á¹¹Óësock½á¹¹ÊÇͬһÊÂÎïµÄÁ½¸ö·½Ãæ¡£Èç¹û˵socket½á¹¹ÊÇÃæÏò½ø³ÌºÍϵͳµ÷ÓýçÃæµÄ£¬ÄÇôsock½á¹¹¾ÍÊÇÃæÏòµ×²ãÇý¶¯³ÌÐòµÄ¡£¿ÉÊÇ£¬ÎªÊ²Ã´²»°ÑÕâÁ½¸öÊý¾Ý½á¹¹ºÏ²¢³ÉÒ»¸öÄØ£¿
ÎÒÃÇ˵Ì×½Ó×ÖÊÇÒ»ÖÖÌØÊâµÄÎļþϵͳ£¬Òò´Ë£¬inode½á¹¹ÄÚ²¿µÄunionµÄÒ»¸ö³É·Ö¾ÍÓÃ×÷socket½á¹¹£¬Æä¶¨ÒåÈçÏ£º
<span style="font-family:SimSun;font-size:12px;">struct inode £û ¡ union { ¡ struct socket socket_i; } }</span> |
ÓÉÓÚÌ×½Ó×Ö²Ù×÷µÄÌØÊâÐÔ£¬Õâ¸ö½á¹¹ÖÐÐèÒª´óÁ¿µÄ½á¹¹³É·Ö¡£¿ÉÊÇ£¬Èç¹û°ÑÕâЩ½á¹¹³É·ÖÈ«¶¼·ÅÔÚsocket½á¹¹ÖУ¬Ôòinode½á¹¹ÖеÄÕâ¸öunion¾Í»á±äµÃºÜ´ó£¬´Ó¶øinode½á¹¹Ò²»á±äµÃºÜ´ó£¬¶ø¶ÔÓÚÆäËûÎļþϵͳ£¬Õâ¸öunion³É·Ö²¢²»ÐèÒªÄÇôÅÓ´ó¡£Òò´Ë£¬¾Í°ÑÌ×½Ó×ÖËùÐèµÄÕâЩ½á¹¹³É·Ö²ð³ÉÁ½²¿·Ö£¬°ÑÓëÎļþϵͳ¹ØÏµ±È½ÏÃÜÇеÄÄÇÒ»²¿·Ö·ÅÔÚsocket½á¹¹ÖУ¬°ÑÓëͨÐŹØÏµ±È½ÏÃÜÇеÄÄÇÒ»²¿·ÖÔòµ¥¶À×é³ÉÒ»¸öÊý¾Ý½á¹¹£¬¼´sock½á¹¹¡£ÓÉÓÚÕâÁ½²¿·ÖÊý¾ÝÔÚÂß¼Éϱ¾À´¾ÍÊÇÒ»ÌåµÄ£¬ËùÒÔҪͨ¹ýÖ¸Õ뻥ÏàÖ¸Ïò¶Ô·½£¬ÐγÉÒ»¶ÔÒ»µÄ¹ØÏµ¡£
°ó¶¨±¾µØIPµØÖ·ºÍ¶Ë¿Ú
ΪÁ˼àÌý´«ÈëµÄ Internet Á¬½ÓÇëÇó£¬Ã¿¸ö·þÎñÆ÷¶¼ÐèÒª½¨Á¢Ò»¸ö INET
BSD Ì×½Ó×Ö£¬²¢ÇÒ½«×Ô¼ºµÄµØÖ·°ó¶¨µ½¸ÃÌ×½Ó×Ö¡£°ó¶¨²Ù×÷Ö÷ÒªÔÚ INET Ì×½Ó×Ö²ãÖнøÐУ¬»¹ÐèÒªµ×²ã TCP
²ãºÍ IP ²ãµÄijЩ֧³Ö¡£½«µØÖ·°ó¶¨µ½Ä³¸öÌ×½Ó×ÖÉÏÖ®ºó£¬¸ÃÌ×½Ó×־Ͳ»ÄÜÓÃÀ´½øÐÐÈÎºÎÆäËûµÄͨѶ£¬Òò´Ë£¬¸Ã
socketÊý¾Ý½á¹¹µÄ״̬±ØÐëΪ TCP_CLOSE¡£´«µÝµ½°ó¶¨²Ù×÷µÄ sockaddr Êý¾Ý½á¹¹Öаüº¬Òª°ó¶¨µÄ
IPµØÖ·£¬ÒÔ¼°Ò»¸ö¿ÉÑ¡µÄ¶Ë¿ÚµØÖ·¡£Í¨³£¶øÑÔ£¬Òª°ó¶¨µÄµØÖ·Ó¦¸ÃÊǸ³Óèij¸öÍøÂçÉ豸µÄ IP µØÖ·£¬¶ø¸ÃÍøÂçÉ豸Ӧ¸ÃÖ§³Ö
INET µØÖ·×壬²¢ÇÒ¸ÃÉ豸ÊÇ¿ÉÓõġ£ÀûÓà ifconfig ÃüÁî¿É²é¿´µ±Ç°»î¶¯µÄÍøÂç½Ó¿Ú¡£±»°ó¶¨µÄ IP
µØÖ·±£´æÔÚ sock Êý¾Ý½á¹¹µÄrcv_saddr ºÍ saddr ÓòÖУ¬ÕâÁ½¸öÓò·Ö±ðÓÃÓÚ¹þÏ£²éÕҺͷ¢ËÍÓõÄ
IP µØÖ·¡£¶Ë¿ÚµØÖ·ÊÇ¿ÉÑ¡µÄ£¬Èç¹ûûÓÐÖ¸¶¨£¬µ×²ãµÄÖ§³ÖÍøÂç»áÑ¡ÔñÒ»¸ö¿ÕÏеĶ˿ڡ£Ê¹ÓÃbindº¯Êý.
/* Give the socket FD the local address ADDR (which is LEN bytes long). */ extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) __THROW; |
´Ëº¯Êý½«Ö¸¶¨µÄsocketÓë¶ÔÓ¦ÍøÂçµØÖ·°ó¶¨,³É¹¦·µ»Ø0,ʧ°Ü·µ»Ø-1
·þÎñÆ÷³ÌÐòËù¼àÌýµÄÍøÂçµØÖ·ºÍ¶Ë¿ÚºÅͨ³£Êǹ̶¨²»±äµÄ£¬¿Í»§¶Ë³ÌÐòµÃÖª·þÎñÆ÷³ÌÐòµÄµØÖ·ºÍ¶Ë¿ÚºÅºó¾Í¿ÉÒÔÏò·þÎñÆ÷·¢ÆðÁ¬½Ó£¬Òò´Ë·þÎñÆ÷ÐèÒªµ÷ÓÃbind°ó¶¨Ò»¸ö¹Ì¶¨µÄÍøÂçµØÖ·ºÍ¶Ë¿ÚºÅ¡£bind()³É¹¦·µ»Ø0£¬Ê§°Ü·µ»Ø-1¡£
bind()µÄ×÷ÓÃÊǽ«²ÎÊýsockfdºÍmyaddr°ó¶¨ÔÚÒ»Æð£¬Ê¹sockfdÕâ¸öÓÃÓÚÍøÂçͨѶµÄÎļþÃèÊö·û¼àÌýmyaddrËùÃèÊöµÄµØÖ·ºÍ¶Ë¿ÚºÅ¡£Ç°Ãæ½²¹ý£¬struct
sockaddr *ÊÇÒ»¸öͨÓÃÖ¸ÕëÀàÐÍ£¬myaddr²ÎÊýʵ¼ÊÉÏ¿ÉÒÔ½ÓÊܶàÖÖÐÒéµÄsockaddr½á¹¹Ì壬¶øËüÃǵij¤¶È¸÷²»Ïàͬ£¬ËùÒÔÐèÒªµÚÈý¸ö²ÎÊýaddrlenÖ¸¶¨½á¹¹ÌåµÄ³¤¶È¡£ÎÒÃǵijÌÐòÖжÔmyaddr²ÎÊýÊÇÕâÑù³õʼ»¯µÄ£º
<span style="font-family:SimSun;font-size:12px;">bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT);</span> |
Ê×ÏȽ«Õû¸ö½á¹¹ÌåÇåÁ㣬ȻºóÉèÖõØÖ·ÀàÐÍΪAF_INET£¬ÍøÂçµØÖ·ÎªINADDR_ANY£¬Õâ¸öºê±íʾ±¾µØµÄÈÎÒâIPµØÖ·£¬ÒòΪ·þÎñÆ÷¿ÉÄÜÓжà¸öÍø¿¨£¬Ã¿¸öÍø¿¨Ò²¿ÉÄܰ󶨶à¸öIPµØÖ·£¬ÕâÑùÉèÖÿÉÒÔÔÚËùÓеÄIPµØÖ·ÉϼàÌý£¬Ö±µ½Óëij¸ö¿Í»§¶Ë½¨Á¢ÁËÁ¬½Óʱ²ÅÈ·¶¨ÏÂÀ´µ½µ×ÓÃÄĸöIPµØÖ·£¬¶Ë¿ÚºÅΪSERV_PORT£¬ÎÒÃǶ¨ÒåΪ8000¡£
µ±µ×²ãÍøÂçÉ豸½ÓÊܵ½Êý¾Ý°üʱ£¬Ëü±ØÐ뽫Êý¾Ý°ü´«µÝµ½ÕýÈ·µÄ INET ºÍ
BSD Ì×½Ó×ÖÒÔ±ã½øÐд¦Àí£¬Òò´Ë£¬TCPά»¤¶à¸ö¹þÏ£±í£¬ÓÃÀ´²éÕÒ´«Èë IP ÏûÏ¢µÄµØÖ·£¬²¢½«ËüÃǶ¨Ïòµ½ÕýÈ·µÄsocket/sock
¶Ô¡£TCP ²¢²»Ôڰ󶨹ý³ÌÖн«°ó¶¨µÄ sock Êý¾Ý½á¹¹Ìí¼Óµ½¹þÏ£±íÖУ¬ÔÚÕâÒ»¹ý³ÌÖУ¬Ëü½ö½öÅжÏËùÇëÇóµÄ¶Ë¿ÚºÅµ±Ç°ÊÇ·ñÕýÔÚʹÓá£ÔÚ¼àÌý²Ù×÷ÖУ¬¸Ã
sock ½á¹¹²Å±»Ìí¼Óµ½ TCP µÄ¹þÏ£±íÖС£
¼àÌýÍøÂç
°ó¶¨ÁËipÐÅÏ¢ºÍ¶Ë¿ÚÐÅÏ¢µÄsocket¶ÔÏó»¹²»ÄܽøÐÐtcpͨѶ,ÒòΪµ±Ç°»¹Ã»ÓÐÄÜÁ¦¼àÌýÍøÂçÇëÇó,Òò´Ë,¶ÔÓÚÃæÏòÁ¬½ÓµÄÓû§À´Ëµ,·þÎñÆ÷¶Ëͨ³£ÐèÒªµ÷ÓÃlistenº¯Êýʹ¸Ãsocket¶ÔÏó¼àÌýÍøÂç,º¯ÊýÉùÃ÷ÈçÏÂ:
/* Prepare to accept connections on socket FD. N connection requests will be queued before further requests are refused. Returns 0 on success, -1 for errors. */ extern int listen (int __fd, int __n) __THROW; |
listen()ÓÃÀ´µÈ´ý²ÎÊýs µÄsocketÁ¬Ïß¡£²ÎÊýbacklogÖ¸¶¨Í¬Ê±ÄÜ´¦ÀíµÄ×î´óÁ¬½ÓÒªÇó£¬Èç¹ûÁ¬½ÓÊýÄ¿´ï´ËÉÏÏÞÔòclient¶Ë½«ÊÕµ½ECONNREFUSEDµÄ´íÎó¡£Listen()²¢Î´¿ªÊ¼½ÓÊÕÁ¬Ïߣ¬Ö»ÊÇÉèÖÃsocketΪlistenģʽ£¬ÕæÕý½ÓÊÕclient¶ËÁ¬ÏßµÄÊÇaccept()¡£Í¨³£listen()»áÔÚsocket()£¬bind()Ö®ºóµ÷Ó㬽Ó×Ųŵ÷ÓÃaccept()¡£
·µ»ØÖµ
³É¹¦Ôò·µ»Ø0£¬Ê§°Ü·µ»Ø-1£¬´íÎóÔÒò´æÓÚerrno
¸½¼Ó˵Ã÷
listen()Ö»ÊÊÓÃSOCK_STREAM»òSOCK_SEQPACKETµÄsocketÀàÐÍ¡£Èç¹ûsocketΪAF_INETÔò²ÎÊýbacklog
×î´óÖµ¿ÉÉèÖÁ128¡£
´íÎó´úÂë
EBADF ²ÎÊýsockfd·ÇºÏ·¨socket´¦Àí´úÂë
EACCESS ȨÏÞ²»×ã
EOPNOTSUPP Ö¸¶¨µÄsocket²¢Î´Ö§Ô®listenģʽ¡£
¿Í»§¶Ë·¢ÆðÁ¬½Ó
Èç¹û·þÎñÆ÷ÒѾ¼àÌýÍøÂç,ÇÒ¿Í»§¶Ë´´½¨ÁËsocket¶ÔÏó,´Ëʱ,¿Í»§¶Ë¿ÉÒÔʹÓÃconnectº¯ÊýÓë·þÎñÆ÷½¨Á¢Á¬½Ó.ÉùÃ÷ÈçÏÂ
/* Open a connection on socket FD to peer at ADDR (which LEN bytes long). For connectionless socket types, just set the default address to send to and the only address from which to accept transmissions. Return 0 on success, -1 for errors. This function is a cancellation point and therefore not marked with __THROW. */ extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); |
º¯Êý˵Ã÷
connect()ÓÃÀ´½«²ÎÊýsockfd µÄsocket Á¬ÖÁ²ÎÊýserv_addr
Ö¸¶¨µÄÍøÂçµØÖ·¡£½á¹¹sockaddrÇë²Î¿¼bind()¡£²ÎÊýaddrlenΪsockaddrµÄ½á¹¹³¤¶È¡£
·µ»ØÖµ
³É¹¦Ôò·µ»Ø0£¬Ê§°Ü·µ»Ø-1£¬´íÎóÔÒò´æÓÚerrnoÖС£
´íÎó´úÂë
EBADF ²ÎÊýsockfd ·ÇºÏ·¨socket´¦Àí´úÂë
EFAULT ²ÎÊýserv_addrÖ¸ÕëÖ¸ÏòÎÞ·¨´æÈ¡µÄÄÚ´æ¿Õ¼ä
ENOTSOCK ²ÎÊýsockfdΪһÎļþÃèÊö´Ê£¬·Çsocket¡£
EISCONN ²ÎÊýsockfdµÄsocketÒÑÊÇÁ¬Ïß״̬
ECONNREFUSED Á¬ÏßÒªÇó±»server¶Ë¾Ü¾ø¡£
ETIMEDOUT ÆóͼÁ¬ÏߵIJÙ×÷³¬¹ýÏÞ¶¨Ê±¼äÈÔδÓÐÏìÓ¦¡£
ENETUNREACH ÎÞ·¨´«ËÍÊý¾Ý°üÖÁÖ¸¶¨µÄÖ÷»ú¡£
EAFNOSUPPORT sockaddr½á¹¹µÄsa_family²»ÕýÈ·¡£
EALREADY socketΪ²»¿É×è¶ÏÇÒÏÈǰµÄÁ¬Ïß²Ù×÷»¹Î´Íê³É
·þÎñÆ÷½ÓÊÜÁ¬½Ó
Èç¹û·þÎñÆ÷¶Ë¼àÌýµ½¿Í»§¶ËµÄÁ¬½ÓÇëÇó,ÔòÐèÒªµ÷ÓÃacceptº¯Êý½ÓÊÕÇëÇó.Èç¹ûûÓмàÌýµ½¿Í»§¶ËµÄÁ¬½ÓÇëÇó,´Ëº¯Êý´¦ÓÚ×èÈû״̬.ÉùÃ÷ÈçÏÂ:
/* 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. */ extern int accept (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len); #ifdef __USE_GNU /* Similar to 'accept' but takes an additional parameter to specify flags. This function is a cancellation point and therefore not marked with __THROW. */ extern int accept4 (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len, int __flags); |
º¯Êý˵Ã÷
accept()ÓÃÀ´½ÓÊܲÎÊýsµÄsocketÁ¬Ïß¡£²ÎÊýsµÄsocket±ØÐèÏȾbind()¡¢listen()º¯Êý´¦Àí¹ý£¬µ±ÓÐÁ¬Ïß½øÀ´Ê±accept()»á·µ»ØÒ»¸öеÄsocket´¦Àí´úÂ룬ÍùºóµÄÊý¾Ý´«ËÍÓë¶ÁÈ¡¾ÍÊǾÓÉеÄsocket´¦Àí£¬¶øÔÀ´²ÎÊýsµÄsocketÄܼÌÐøÊ¹ÓÃaccept()À´½ÓÊÜеÄÁ¬ÏßÒªÇó¡£Á¬Ï߳ɹ¦Ê±£¬²ÎÊýaddrËùÖ¸µÄ½á¹¹»á±»ÏµÍ³ÌîÈëÔ¶³ÌÖ÷»úµÄµØÖ·Êý¾Ý£¬²ÎÊýaddrlenΪscokaddrµÄ½á¹¹³¤¶È¡£¹ØÓڽṹsockaddrµÄ¶¨ÒåÇë²Î¿¼bind()¡£
·µ»ØÖµ
³É¹¦Ôò·µ»ØÐµÄsocket´¦Àí´úÂ룬ʧ°Ü·µ»Ø-1£¬´íÎóÔÒò´æÓÚerrnoÖС£
´íÎó´úÂë
EBADF ²ÎÊýs ·ÇºÏ·¨socket´¦Àí´úÂë¡£
EFAULT ²ÎÊýaddrÖ¸ÕëÖ¸ÏòÎÞ·¨´æÈ¡µÄÄÚ´æ¿Õ¼ä¡£
ENOTSOCK ²ÎÊýsΪһÎļþÃèÊö´Ê£¬·Çsocket¡£
EOPNOTSUPP Ö¸¶¨µÄsocket²¢·ÇSOCK_STREAM¡£
EPERM ·À»ðǽ¾Ü¾ø´ËÁ¬Ïß¡£
ENOBUFS ϵͳµÄ»º³åÄÚ´æ²»×ã¡£
ENOMEM ºËÐÄÄÚ´æ²»×ã¡£
¶Áдsocket¶ÔÏó
socket¶ÔÏóÊÇÒ»ÀàÌØÊâµÄÎļþ,Òò´Ë¿ÉÒÔʹÓÃLinuxϵͳµÄI/Oϵͳµ÷ÓÃreadº¯ÊýÀ´¶Ásocket¶ÔÏóÊý¾Ý,writeº¯ÊýÏòsocket¶ÔÏóдÈëÊý¾Ý.
º¯ÊýÉùÃ÷ÓëʹÓúÍ֮ǰµÄÒ»Ñù.
TCP·¢ËͽÓÊÕÊý¾Ý
sendºÍrecvº¯ÊýרÃÅʵÏÖÃæÏòÁ¬½ÓµÄsocket¶ÔÏó¶Áд²Ù×÷.
/* Send N bytes of BUF to socket FD. Returns the number sent or -1. This function is a cancellation point and therefore not marked with __THROW. */ extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); /* Read N bytes into BUF from socket FD. Returns the number read or -1 for errors. This function is a cancellation point and therefore not marked with __THROW. */ extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); |
¹ØÓÚsendº¯Êý
µÚÒ»¸ö²ÎÊýÊÇ·¢Ë͵ÄÄ¿±êsocket¶ÔÏó,µÚ¶þ¸ö²ÎÊýÊÇÓû·¢Ë͵ÄÊý¾ÝλÖÃ,µÚÈý¸ö²ÎÊýÊÇÊý¾ÝµÄ´óС.µÚËĸö²ÎÊý²Ù×÷flags,Ö§³ÖµÄֵλ0»òÕßMSG_OOB(·¢ËÍ´øÍâÊý¾Ý)µÈ.ʹÓÃsendº¯Êýʱ½«flagsÖÃΪ0ÓëʹÓÃwriteº¯ÊýÍêÈ«Ïàͬ.
Ö´Ðгɹ¦·µ»ØÊý¾Ý´óС,ʧ°Ü·µ»Ø-1
¹ØÓÚrecvº¯Êý
¸÷¸ö²ÎÊýÀàËÆÓÚsendº¯Êý¸÷¸ö²ÎÊý¶¨Òå,Æä½«´ÓfdËùÖ¸µÄsocketÖжÁÈ¡n×Ö½ÚÊý¾Ýµ½buffÖÐ.Ö´Ðгɹ¦Ôò·µ»ØÊý¾Ý´óС,ʧ°Ü·µ»Ø-1
Á½¸öº¯ÊýµÄflagsÓÃÀ´ËµÃ÷´¦ÀíÊý¾ÝµÄ·½Ê½,³£¼ûµÄÉùÃ÷ÈçÏÂsocket.hÖж¨Òå:
/* Bits in the FLAGS argument to `send', `recv', et al. */ enum { MSG_OOB = 0x01, /* Process out-of-band data. */ // ´øÍâÊý¾Ý #define MSG_OOB MSG_OOB MSG_PEEK = 0x02, /* Peek at incoming messages. */ // ²é¿´ÍâÀ´ÐÅÏ¢,Ïàͬ²»¶ªÊ§²é¿´µ½µÄÊý¾Ý #define MSG_PEEK MSG_PEEK MSG_DONTROUTE = 0x04, /* Don't use local routing. */ // ±¾µØ²»Â·ÓÉ #define MSG_DONTROUTE MSG_DONTROUTE #ifdef __USE_GNU /* DECnet uses a different name. */ MSG_TRYHARD = MSG_DONTROUTE, # define MSG_TRYHARD MSG_DONTROUTE #endif MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ #define MSG_CTRUNC MSG_CTRUNC MSG_PROXY = 0x10, /* Supply or ask second address. */ #define MSG_PROXY MSG_PROXY MSG_TRUNC = 0x20, #define MSG_TRUNC MSG_TRUNC MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ // ²»×èÈû #define MSG_DONTWAIT MSG_DONTWAIT MSG_EOR = 0x80, /* End of record. */ #define MSG_EOR MSG_EOR MSG_WAITALL = 0x100, /* Wait for a full request. */ #define MSG_WAITALL MSG_WAITALL // µÈ´ýËùÓÐÊý¾Ý MSG_FIN = 0x200, #define MSG_FIN MSG_FIN MSG_SYN = 0x400, #define MSG_SYN MSG_SYN MSG_CONFIRM = 0x800, /* Confirm path validity. */ #define MSG_CONFIRM MSG_CONFIRM MSG_RST = 0x1000, #define MSG_RST MSG_RST MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ #define MSG_ERRQUEUE MSG_ERRQUEUE MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ #define MSG_NOSIGNAL MSG_NOSIGNAL MSG_MORE = 0x8000, /* Sender will send more. */ #define MSG_MORE MSG_MORE MSG_WAITFORONE = 0x10000, /* Wait for at least one packet to return.*/ #define MSG_WAITFORONE MSG_WAITFORONE MSG_FASTOPEN = 0x20000000, /* Send data in TCP SYN. */ #define MSG_FASTOPEN MSG_FASTOPEN MSG_CMSG_CLOEXEC = 0x40000000 /* Set close_on_exit for file descriptor received through SCM_RIGHTS. */ #define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC }; |
¹Ø±Õsocket¶ÔÏó
ʹÓÃI/OÏàͬµ÷ÓÃcloseº¯Êý.
ÁíÒ»ÖÖÊǵ÷ÓÃshutdownº¯Êý,
/* Shut down all or part of the connection open on socket FD. HOW determines what to shut down: SHUT_RD = No more receptions; SHUT_WR = No more transmissions; SHUT_RDWR = No more receptions or transmissions. Returns 0 on success, -1 for errors. */ extern int shutdown (int __fd, int __how) __THROW; |
TCPÁ¬½ÓÊÇË«ÏòµÄ(¿É¶Á¿Éд),µ±Ê¹ÓÃcloseº¯Êýʱ,»á°Ñ¶Áд¾ù¹Ø±Õ,ÓÐʱºòÏ£ÍûÖ»¹Ø±ÕÒ»¸ö·½Ïò,ÕâʱҪÓÃshutdownº¯Êý,ÏàͬÌṩÁËÏÂÃæÈýÖֹرշ½Ê½.
howto = 0 ¹Ø±Õ¶ÁͨµÀ,¿ÉÒÔ¼ÌÐøÏòsocketÃèÊö·ûÖÐд
howto = 1 ¹Ø±ÕдͨµÀ.´Ëʱֻ¿ÉÒÔ¶Á
howto = 2 ¹Ø±Õ¶Áд
»ñÈ¡socket±¾µØÒÔ¼°¶Ô¶ËÐÅÏ¢
/* Put the local address of FD into *ADDR and its length in *LEN. */ extern int getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __len) __THROW; /* Put the address of the peer connected to socket FD into *ADDR (which is *LEN bytes long), and its actual length into *LEN. */ extern int getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __len) __THROW; |
|