网络编程学习_基本socket函数

知其然更要知其所以然,虽然这几个函数已经写过不少次,却一直不知道它们究竟做了什么

一,socket 

int socket(int family,int type,int protocol);

仅仅申请了一个sock fd而已,并没有与任何地址相关联,对于TCP, family=AF_INET, type=SOCK_STREAM,protocol=0/IPPOROTO_TCP

二,connect

int connect(int sockfd,const struct sockaddr* servaddr,socklen_t addrlen);

这个函数完成了TCP的三次握手,可以根据errno得到出错原因,一般是超时或服务器端口没开

三,bind

int bind(int sockfd,const struct socaddr* myaddr,socklen_t addrlen);

这个函数完成sockfd与地址(包括ip和端口)的绑定, 注意如果不绑定,内核将会随机分配(ip或端口),一般客户端不绑定,服务器需绑定一个端口

四,listen

int listen(int sockfd,int backlog);

当一个socket创建后,默认是主动套接字, 这个函数将其转成被动套接字. 按TCP状态来说,从CLOSED转成LISTEN

backlog一般是5, 大概限定了允许正在进行三次握手过程的连接的数量

五,accept

int accept(int sockfd,struct sockaddr* cliaddr,socklen_t* addrlen);

服务器函数,用于从已完成三次握手的队列头返回一个已完成连接, 如果没有则一直阻塞,并返回新连接的sockfd

六,fork

pid_t  fork(void);

新建一个进程,一次调用两次返回,在子进程返回0,父进程返回子进程id. 多进程是实现服务器并发的方法之一,但显然多线程更为常用

当fork出一个新进程后,每个sockfd的引用计数都+1,而只有一个fd的引用计数降为0后才会被关闭(四次挥手),而每次close只是引用计数-1, 所以子进程和父进程都要关闭fd.

通常父进程会立刻关闭accept产生的新fd,子进程会立刻关闭listen fd, 代码如下:

.....
while(1)
{
    newfd=accept(listenfd,&addr,&len);
    if((pid=fork())==0)
    {
         //子进程
         close(listenfd);
         ......
         close(newfd);
         exit(0)
    }
    //父进程
    close(newfd);
}

七,getsockname和getpeername

int getsockname(int sockfd,struct sockaddr* localaddr,socklen_t* addrlen);

int getpeername(int sockfd,struct sockaddr* peeraddr,socklen_t* addrlen);

这两个函数从套接字获取绑定于其上的本地或远程地址



你可能感兴趣的:(网络编程学习_基本socket函数)