TCP socket API详解

下面介绍程序中用到的socket API,这些函数都在sys/socket.h中。

socket():

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器) 
int socket(int domain, int type, int protocol);
  • socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符;
  • 应用程序可以像读写文件一样用read/write在网络上收发数据;
  • 如果socket()调用出错则返回-1;
  • 对于IPv4,family(域)参数指定为AF_INET;
  • 对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议
  • protocol参数指定为0即可。

bind():

// 绑定端口号 (TCP/UDP, 服务器)      
int bind(int socket, const struct sockaddr *address,          socklen_t address_len);
  • 客户端不需要绑定端口号,服务器必须绑定端口号
  • 服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后 就可以向服务器发起连接; 服务器需要调用bind绑定一个固定的网络地址和端口号;
  • bind()成功返回0,失败返回-1。
  • bind()的作用是将参数sockfd和myaddr绑定在一起, 使sockfd这个用于网络通讯的文件描述符监听 myaddr所描述的地址和端口号;

listen():

// 开始监听socket (TCP, 服务器) 
int listen(int socket, int backlog);
  • listen()声明sockfd处于监听状态, 并且最多允许有backlog个客户端处于连接等待状态, 如果接收到更多 的连接请求就忽略, 这里设置不会太大(一般是5);
  • backlog不能太大的原因:用一个例子说明:比如说赛格里的饭店人一般都会较多,老板会在外边摆一些凳子让顾客在那坐着排队,如果老板摆上几百个凳子的话,那就没意思了,只适合摆十几个就可以了(即,不能没有,不能太多,是为了提高效率)
  • listen()成功返回0,失败返回-1

accept():

// 接收请求 (TCP, 服务器) 
int accept(int socket, struct sockaddr* address,          socklen_t* address_len);
  • 三次握手完成后, 服务器调用accept()接受连接;
  • 如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来;
  • addr是一个传出参数,accept()返回时传出客户端的地址和端口号;
  • 如果给addr 参数传NULL,表示不关心客户端的地址;

connect():

// 建立连接 (TCP, 客户端) 
int connect(int sockfd, const struct sockaddr *addr,          socklen_t addrlen)
  • 客户端需要调用connect()连接服务器
  • connect和bind的参数形式一致, 区别在于bind的参数是自己的地址, 而connect的参数是对方的地址;
  • connect()成功返回0,出错返回-1

socket用完就要关掉,不关的话会导致下次打开会失败。