`
oolala
  • 浏览: 103693 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
09c341db-7f05-3f2b-a572-9ee69a5d8a77
unix环境高级编程
浏览量:22850
社区版块
存档分类
最新评论

UNIX网络编程卷一:4 基本套接字编程

 
阅读更多
1、socket函数
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
       int socket(int domain, int type, int protocol);

domain参数指明协议族,该参数也往往被称为协议域

type      参数指明套接字类型
protocol协议类型


 
 
 
 
 
socket函数domain常值
AF_INET    IPV4协议
AF_INET6  IPV6协议
AF_LOCAL UNIX域协议
AF_ROUTE 路由套接字
AF_KEY      密钥套接字
 
socket函数type常值
SOCK_STREAM  字节流套接字
SOCK_DGRAM   数据报套接字
SOCK_SEQPACKET  有序分组套接字
SOCK_RAW              原始套接字
 
socket函数的type常值
IPPROTO_CP     TCP传输协议
IPPROTO_UDP  UDP传输协议
IPROTO_SCTP   SCTP传输协议
 
socket函数中domain和type参数的组合
 
socket函数在成功时返回一个小的非负整数值,它与文件描述符类似,我们把它称为套接字描述符(scoket descriptor)  sockfd
 
 

2、connect函数
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
 
       int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
sockfd是socket函数返回的套接字描述符
 
如果是TCP套接字,调用connect函数将激发TCP的三路握手过程,而且仅在连接建立成功或出错时才返回。
 
connect函数导致当前套接字从closed状态转换到SYN_SENT状态,或成功则再转换到ESTABLISHIED状态。
若connect失败则该套接字不再可用,必须关闭,我们不能对这样的套接字再次调用connect。
当循环调用connect函数为给定主机尝试各个ip直到有一个成功,在每次connect失败后,都必须close当前的套接字描述符并重新调用socket
 

3、bind函数
    bind函数把一个本地协议地址赋予一个套接字
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
 
       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
如果TCP客户端或服务器未曾调用bind绑定一个端口,
 
对于ipv4,通配地址由常值INADDR_ANY来指定,其值一般为0.它告知内核去选择ip地址
struct sockaddr_in servaddr;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 
 

4、listen函数
    1)当socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说,它是一个将调用connect发起连接的客户端套接字。
    listen函数把一个未连接的套接字转换成一个被动套接字,指示内核应接受指向该套接字的连接请求。
    调用listen导致套接字从close状态转换到LISTEN状态。
    
    2)本函数第二个参数规定了内核应该为相应套接字排队的最大连接个数
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
 
       int listen(int sockfd, int backlog);
内核为任何一个给定的监听套接字维护二个队列:
1)未完成连接队列(incomplete connection queue)
    每个这样的SYN分节对应其中一项:已由某个客户发出并到达服务器,而服务器正在等待完成相应的TCP三路握手过程。这些套接字处于SYN_RCVD状态。
2)已完成连接队列(completed connection queue)
    每个已完成TCP三路握手过程的客户对应其中一项。这些套接字处于ESTABLISHED状态。
 
 
5、accept函数
    accept函数由TCP服务器调用,用于从已完成队列头返回下一个已完成连接。
    如果已完成连接队列为空,那么进程被投入睡眠
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数sockaddr  addrlen用来返回已连接的对端进程(客户)的协议地址。addrlen是值-结果参数
 
如果accept成功,那么其返回值是由内核自动生成的一个全新描述符,代表与所返回客户的TCP连接。
称第一个参数为监听套接字(listening sock)描述符,称它的返回值为已连接套接字(connected socket),它在服务器的生命周期内一直存在。
内核为每个由服务器进程接受的客户连接创建一个已连接套接字,当服务器完成对某个给定客户的服务时,相应的已连接套接字就被关闭。
 
 
6、fork和exec
 
7、并发服务器
    

 
 
    当一个连接建立时,accept返回,服务器接着调用fork,然后由子进程服务客户,父进程则等待另一个连接(通过监听套接字listenfd)。既然新的客户由子进程提供服务,父进程就关闭已连接套接字。
    该函数返回时,子进程中显示的关闭已连接套接字。这一点并非必须,因为下一个语句就是调用exit,而进程终止处理部分工作就是关闭所有由内核打开的文件描述符。
    父进程对connfd调用close没有终止与客户的连接?每个文件或套接字都有一个引用计数。引用计数在文件表项中维护,它是当前打开着的引用该文件或套接字的描述符的个数。该套接字真正的清理和释放资源要等到其引用计数值达到0时才会发生。这会在稍后子进程也关闭connfd时发生。
 
 
7、close
       #include <unistd.h>
 
       int close(int fd);
    
描述符引用计数
    并发服务器中父进程关闭已连接套接字只是导致相应描述符的引用计数减1.既然引用计算值仍大于0,这个close调用并不引发TCP的四分组连接终止序列。
对于父进程与子进程共享已连接套接字的并发服务器来说,这正是所期望的。
    确实想在某个TCP连接上发送FIN,改用shutdown代替close
  • 大小: 46 KB
  • 大小: 73.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics