linux网络编程系列TCP及常用接口分析

TCP编程示例图:


头文件:

常用头文件"arpa/inet.h", "sys/socket.h","netinet/in.h"

函数原型:

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

family:通信协议族,IP protocol family为AF_INET(PF_INET),值是2;

type:套接字类型(连接类型)。

SOCK_STREAM(1)为Sequenced, reliable, connection-based byte streams(TCP);

SOCK_DGRAM(2)为Connectionless, unreliable datagrams of fixed maximum length(UDP);

其他还有SOCK_RAW(3), SOCK_RDM(4), SOCK_SEQPACKET(5),SOCKET_PACKET(10)。

protocol:不解释了,没理解,一般写为0,系统自动选择合适的协议。返回:套接字描述符。

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

connect:客户端调用;servaddr套接口地址结构,包含有服务器的IP地址和端口号;返回0成功,-1出错;每当connect失败,都必须关闭套接口,重新调用socket。

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

bind:服务端调用,给套接口分配一个本地协议地址;myaddr包含本地分配的ip和端口;返回0成功,-1出错。客户端不调用bind由内核随意分配一个端口,而服务端必须调用明确指出端口。

int listen(int sockfd, int backlog)

listen:socket函数创建套接口默认为主动套接口(要发起连接的),listen会将未连接的套接口转换成被动套接口(接收连接),返回-1出错0成功。

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

accept:从已完成的连接队列头部返回一个已完成连接;成功返回内核自动生成的一个全新描述字代表与客户端的TCP连接,第一个参数sockfd常称为监听套接口,返回值称为已连接套接口,返回-1出错。cliaddr为客户端的协议地址,addrlen为该地址大小。一个服务器常常只生成一个监听套接口且一直存在,直到该服务器关闭。内核为每个被接受的客户连接创建一个已连接套接口(三路握手已完成的连接)。

监听套接口的两个队列:


int close(int sockfd)

close:将套接口sockfd做上已关闭标记,并立即返回。该描述字不能再用作read或write的参数,但TCP会继续发送已排队待发的数据,然后按照TCP连接终止序列进行操作。

数据读写:

标准读写

ssize_t write(int fd, const void *buf, size_t n)
ssize_t read (int fd, void *buf, size_t n)

网络读写

ssize_t send (int fd, const void *buf, size_t n, int flags)
ssize_t recv (int fd, void *buf, size_t n, int flags)

何时阻塞:

•写阻塞,send buffer is full
•读阻塞,receive buffer is empty

常用结构:

socklen_t表示套接字的大小,4Byte,是一个uint32类型。

struct sockaddr表示套接字的连接地址,通常用struct sockaddr_in代替。二者大小相同,sockaddr_in用了多余的char数组来补齐大小。

struct sockaddr
{
sa_family_t sa_family;//2个字节,地址协议族,unsigned short int
char sa_data[14];//地址
}
struct sockaddr_in
  {
    sa_family_t sin_family; //2Byte
    in_port_t sin_port;     /* Port number.  2Byte*/ 
    struct in_addr sin_addr;    /* Internet address.  4Byte*/

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
         __SOCKADDR_COMMON_SIZE -
         sizeof (in_port_t) -
         sizeof (struct in_addr)];
  };
typedef uint32_t in_addr_t;
struct in_addr
{
    in_addr_t s_addr;
};
#define __SOCKADDR_COMMON_SIZE  sizeof(unsigned short int)
辅助函数:
char *inet_ntoa (struct in_addr __in)

将IP地址由网络字节序转为可理解的点分十进制(net to ascii)

int inet_pton (int af, const char* cp, void* buf)

将点分十进制ip转为网络字节序,af为地址协议族(AF_INET),cp为ip地址(10.8.3.2), buf为保存转换结果的地址。常用如下:

struct sockaddr_in addr;
inet_pton(AF_INET, "10.3.17.75", &addr.sin_addr);
in_addr_t inet_addr (const char *cp)

同inet_pton效果相同,将ip转为网络字节序

struct sockaddr_in sin;
sin.sin_addr.s_addr = inet_addr("10.17.25.34");


原文地址:https://www.cnblogs.com/whuqin/p/4982012.html