基本套接字函数

socket函数
#include <sys/socket.h>
int socket(int family, int type, int protocol);
返回值:成功返回非负描述符,若出错则为-1

family指名协议族,可取:
 AF_INET  IPv4协议
 AF_INET6  IPv6协议
 AF_LOCAL  UNIX域协议
 AF_ROUTE  路由套接字
 AF_KEY 密匙套接字

type指名套接字类型,可取:
 SOCK_STREAM  字节流套接字
 SOCK_DGRAM  数据报套接字
 SOCK_SEQPACKET  有序分组套接字
 SOCK_RAW  原始套接字

protocol指名协议类型常值,或者为0,以选择所给定的family和type组合的系统默认值:
 IPPROTO_TCP  TCP传输协议
 IPPROTO_UDP  UDP传输协议
 IPPROTO_SCTP  SCTP传输协议


connect函数
TCP客户端用connect函数建立与TCP服务器的连接
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *sockaddr, socklen_t addrlen);
返回值:若成功则返回0,出错返回-1
sockfd:socket函数返回的套接字描述符
sockaddr:指向套接字地址结构的指针
addrlen:套接字地址结构的长度

如果是TCP套接字,connect函数将会激发TCP的三路握手过程.仅在建立成功或失败时才返回,出错返回可能的情况:
1.如果TCP客户端长时间没有收到SYN分节的响应,则返回ETIMEOUT错误
2.若服务器对客户的SYN响应市RST(复位),则说明该服务器在客户端指定的端口上没有进程在等待与之连接,客户端在接收到RST后,马上返回ECONNREFUSED错误,这是一种硬错误
3.如果客户端发出的SYN在中间的某个路由上引发了一个"destination unreachable"ICMP错误,则客户端主机的内核会对其进行记录,并继续发送SYN,如果在一段时间内仍未收到相应,则把保存的ICMP错误作为EHOSTUNREACH或ENETUNREACH错误返回给进程;如果按照本地系统的转发表根本就没有路径到达服务器,或是connect调用根本就不等待就返回,也会引发此错误

socket函数创建一个新套结字后,这个套接字一直处于CLOSED状态,调用connect时转移到SYN_SENT状态,若调用成功则再转移到ESTABLISH状态;如果失败则这个套接字不能够再次使用,不能对其再次调用connect函数,必须关闭

bind函数
把一个本地协议地址赋予一个套接字
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
返回值:成功返回0,出错返回-1

调用bind可以指定一个端口号,或是IP地址,或是两者都指定,还可以都不指定
如果不调用bind绑定一个端口,则当调用connect或是listen时,内核就会为相应的套接字选择一个临时端口。
由于bind的第二个参数有const限定词,所以它无法返回内核自动选择的端口和IP,如果想获取到这个值,必须要调用getsockname来返回协议地址。

bind返回的最常见错误是:EADDRINUSE("Address already in use")

listen函数
socket函数创建的套接字是一个主动套接字,是一个将要发起connect连接的客户套接字,listen函数把一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该套接字的连接请求;调用linsten函数会导致套接字从CLOSED状态转换到LISTEN状态.
#include <sys/socket.h>
int listen(int sockfd, int backlog);
返回值:成功返回0,出错返回-1
backlog规定了内核为相应套接字排队的最大连接个数

内核为每一个给定的监听套接字维护两个队列
未完成队列:此队列中的套接字是由客户端发出并已经到达服务器,但是还没有完成TCP三次握手过程的,其处于SYN_RCVD状态
已完成队列:此队列中的套接字是已经完成TCP三路握手过程的,其处于ESTABLISHED状态
两个队列的长度之和应该不超过backlog

accept函数
用于从已完成连接队列队头返回下一个已完成连接的套接字,如果已完成队列为空,则进程被投入睡眠状态
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
返回值:成功返回非负描述符,出错返回-1
cliaddr和addrlen用来返回已连接的客户端的协议地址,如果不关心的话可以设置为空
如果accept成功,则其返回值是由内核自动生成的一个全新描述符,代表与所返回套接字的TCP连接

fork函数
该函数是UNIX中派生新进程的唯一方法
#include <unistd.h>
pid_t fork(void);
返回值:在子进程中为0,在父进程中为子进程ID,出错返回-1

父进程中调用fork之前打开的所有描述符在fork之后由子进程分享

exec函数
在磁盘上的可执行程序文件能够被UNIX执行的唯一方法就是由一个现有进程调用六个exec函数中的一个;exec函数把当前进程映像替换成新的程序文件,并且该新程序通常从main函数开始执行新的程序
#include <unistd.h>
int execl(const char *pathname, const char *arg0, ... /* (char *)0 */);
int execv(const char *pathname, char *const *argv[]);
int execle(const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */);
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */);
int execvp(const char *filename, char *const argv[]);
返回值:成功不返回,出错返回-1

execve是内核中的系统调用,其他五个都是调用execve的库函数

你可能感兴趣的:(linux,unix,socket,NetWork)