网络连接函数
主页 上一层 转换函数 网络连接函数 获取/设置参数

 

初始化sock连接符:

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

函数返回socket描述符,返回-1表示出错

domain参数只能取AF_INET, protocol参数一般取0

应用示例:

TCP方式:sockfd = socket(AF_INET,SOCK_STREAM,0);

UDP方式:sockfd =socket(AF_INET, SOCK_DGRAM,0);

 

绑定端口:

int bind(int sockfd, struct sockaddr *sa, int addrlen);

函数返回-1表示出错,最常见的错误是该端口已经被其他程序绑定。

需要注意的一点:在Linux系统中,1024以下的端口只有拥有root权限的程序才能绑定。

 

连接网络(用于TCP方式):

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

函数返回-1表示出错,可能是连接超时或无法访问。返回0表示连接成功,可以通过sockfd传输数据了。

 

监听端口(用于TCP方式):

int listen(int sockfd, int queue_length);

需要在此前调用bind()函数将sockfd绑定到一个端口上,否则由系统指定一个随机的端口。

接收队列:一个新的Client的连接请求先被放在接收队列中,直到Server程序调用accept函数接受连接请求。

第二个参数queue_length,指的就是接收队列的长度 也就是在Server程序调用accept函数之前最大允许的连接请求数,多余的连接请求将被拒绝。

 

响应连接请求(用于TCP方式):

int accept(int sockfd,struct sockaddr *addr,int *addrlen);

accept()函数将响应连接请求,建立连接并产生一个新的socket描述符来描述该连接,该连接用来与特定的Client交换信息。

函数返回新的连接的socket描述符,错误返回-1

addr将在函数调用后被填入连接对方的地址信息,如对方的IP、端口等。

addrlen作为参数表示addr内存区的大小,在函数返回后将被填入返回的addr结构的大小。

accept缺省是阻塞函数,阻塞直到有连接请求

应用示例:

struct sockaddr_in their_addr; /* 用于存储连接对方的地址信息*/
int sin_size = sizeof(struct sockaddr_in);

… …(依次调用socket(), bind(), listen()等函数)

new_fd = accept(sockfd, &their_addr, &sin_size);
printf(”对方地址: %s\n", inet_ntoa(their_addr.sin_addr));

… …

 

关闭socket连接:

int close(int sockfd);

关闭连接将中断对该socket的读写操作。

关闭用于listen()的socket描述符将禁止其他Client的连接请求。

 

部分关闭socket连接:

int shutdown(int sockfd, int how);

Shutdown()函数可以单方面的中断连接,即禁止某个方向的信息传递。

参数how:

0 - 禁止接收信息
1 - 禁止发送信息
2 - 接收和发送都被禁止,与close()函数效果相同

 

socket轮询选择:

int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

应用于多路同步I/O模式(将在同步工作模式中详细讲解)

FD_ZERO(*set) 清空socket集合
FD_SET(s, *set) 将s加入socket集合
FD_CLR(s, *set) 从socket集合去掉s
FD_ISSET(s, *set) 判断s是否在socket集合中

    常数FD_SETSIZE:集合元素的最多个数

 

等待选择机制:

int poll(struct pollfd *ufds, unsigned int nfds, int timeout);

是select机制的一个变种,应用于多路同步I/O模式(将在同步工作模式中详细讲解)

ufds是pollfd结构的数组,数组元素个数为nfds。

     struct pollfd {
           int fd;           /* file descriptor */
           short events;     /* requested events */
           short revents;    /* returned events */
       };

 

 

接收/发送消息:

TCP方式:

int send(int s, const void *buf, int len, int flags);

int recv(int s, void *buf, int len, int flags);

函数返回实际发送/接收的字节数,返回-1表示出错,需要关闭此连接。

函数缺省是阻塞函数,直到发送/接收完毕或出错

注意:如果send函数返回值与参数len不相等,则剩余的未发送信息需要再次发送

 

UDP方式:

int sendto(int s, const void *buf, int len, int flags, const struct sockaddr *to, int tolen);

int recvfrom(int s,void *buf, int len, int flags, struct sockaddr *from, int *fromlen);

与TCP方式的区别:

需要指定发送/接收数据的对方(第五个参数to/from)

函数返回实际发送/接收的字节数,返回-1表示出错。

函数缺省是阻塞函数,直到发送/接收完毕或出错

注意:如果send函数返回值与参数len不相等,则剩余的未发送信息需要再次发送

 

基于消息的方式:

int sendmsg(int s, const struct msghdr *msg, int flags);

int recvmsg(int s, struct msghdr *msg, int flags);

发送/接收一个消息,消息使用如下数据结构:

struct msghdr {

void * msg_name; /* optional address */

socklen_t msg_namelen; /* size of address */

struct iovec * msg_iov; /* scatter/gather array */

size_t msg_iovlen; /* # elements in msg_iov */

void * msg_control; /* ancillary data, see below */

socklen_t msg_controllen; /* ancillary data buffer len */

int msg_flags; /* flags on received message */

};

这种方式可以使用面向连接和无连接两种方式,灵活性较大,但不太常用,将在后面的程序示例(网络仿真设备)中解释工作流程。

 

标志位:

上面这六个发送/接收函数均有一个参数flags,用来指明数据发送/接收的标志,常用的标志主要有:

MSG_PEEK 对数据接收函数有效,表示读出网络数据后不清除已读的数据

MSG_WAITALL 对数据接收函数有效,表示一直执行直到buf读满、socket出错或者程序收到信号。

MSG_DONTWAIT 对数据发送函数有效,表示不阻塞等待数据发送完后返回,而是直接返回。(只对非阻塞socket有效)

MSG_NOSIGNAL 对发送接收函数有效,表示在对方关闭连接后出错但不发送SIGPIPE信号给程序。

MSG_OOB 对发送接收都有效,表示读/写带外数据(out-of-band data)

 

带外数据实例图