Linux Socket 编程相关函数

struct sockaddr and struct sockaddr_in

struct sockaddr定义在<sys/socket.h>头文件中,原型如下

/* Structure describing a generic socket address.  */
struct sockaddr{
	//unsigned short int sa_family;
	//表明协议族,通常为:AF_INET (IPV4) AF_INET6(IPV6) 
	//PF_INET含义同AF_INET一样
    __SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */
    //存放ip地址的字符形式如:0.0.0.0
    char sa_data[14];		/* Address data.  */
};

struct sockaddr_in 定义在<netinet/in.h>中,原型如下:

/* Internet address.  */
typedef uint32_t in_addr_t;
struct in_addr{
    in_addr_t s_addr;
};
/* Structure describing an Internet socket address.  */
struct sockaddr_in{
	//short  int  sin_family;
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;			/* Port number.  */
    struct in_addr sin_addr;		/* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];
 };

socket 函数

函数原型如下

	/* Create a new socket of type TYPE in domain DOMAIN, using
  	 protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
  	 Returns a file descriptor for the new socket, or -1 for errors.  */
	extern int socket (int __domain, int __type, int __protocol) __THROW;

参数含义如下:
__domain 指明通信域,如 PF_UNIUX(unix域)PF_INET(IPV4) PF_INET6(IPv6)

__type 指明通信类型,最常用SOCK_STREAM(面向链接的可靠方式TCP),SOCK_DGRAM(非面向链接的非可靠方式UDP),SOCK_STREAM是数据流,一般都是TCP/IP协议的编程,SOCK_DGRAM是数据包,是udp协议网络编程

__protocol指定需要使用的协议,可以是:IPPROTO_TCPIPPROTO_UDP使用0则根据前两个参数使用默认地址

NOTE:创建成功则返回一个文件描述符,-1则创建失败

bind函数

函数原型如下:

/* Give the socket FD the local address ADDR (which is LEN bytes long).  */
extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)__THROW;

参数含义
__fd 调用scoket()函数创建成功的文件描述符(file descriptor)

__addr 的类型其实是struct sockaddr * 一个本地地址

__len 第二个参数的大小

使用例子

	struct sockaddr_in addr;
    //创建socket,获取一个socket描述符
    if ((listen_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr, "%s(): cannot create socket", __FUNCTION__);
        return -1;
    }
    //设置server的地址同通信协议
    memset(&addr, 0, sizeof(struct sockaddr_in));
    //协议族: AF_INET AF_INET6 AF_LOCAL
    addr.sin_family = AF_INET;
    //取本地任意一个地址进行通信
    // uint32_t htonl(uint32_t hostlong) 将主机无符号长整型转化为网络字节
    //INADDR_ANY=0.0.0.0
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    // uint16_t htons(uint16_t hostshort) 将hostshort 转化为网络字节序
    //网络字节采用大端模式(big-ending),高位存放在低地址
    addr.sin_port = htons(PORT);
    if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0) {
        fprintf(stderr, "%s(): bind() failed", __FUNCTION__);
        goto failed;
    }

listen函数

函数原型如下:

/* Prepare to accept connections on socket FD.
   N connection requests will be queued before further requests are refused.
   Returns 0 on success, -1 for errors.  */
extern int listen (int __fd, int __n) __THROW;

参数含义
__fd 调用scoket()函数创建成功的文件描述符(file descriptor)

__n 等待连接队列的最大长度

NOTE:返回0代表成功 -1代表失败

accept函数

函数原型如下:

/* Await a connection on socket FD.
   When a connection arrives, open a new socket to communicate with it,
   set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
   peer and *ADDR_LEN to the address's actual length, and return the
   new socket's descriptor, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len);

参数含义:
__fd 调用scoket()函数创建成功的文件描述符(file descriptor)

__addr 的类型其实是struct sockaddr * 链接成功会把客户端的地址信息存入改结构体

__restrict __addr_len 第二个传入的参数修改以后的实际大小

NOTE:链接成功则返回一个文件描述符(以后的通信都使用它),-1则创建失败

connect函数

函数原型如下:

/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
   For connectionless socket types, just set the default address to send to
   and the only address from which to accept transmissions.
   Return 0 on success, -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);

参数含义:
__fd 客户端调用scoket()函数创建成功的文件描述符(file descriptor)

__addr 的类型其实是struct sockaddr *需要建立链接的服务端的地址和端口信息(必须是网络字节序)

__len 第二个参数结构体的大小

NOTE:返回0代表成功 -1代表失败

使用例子:

    struct sockaddr_in clientAddr;
    struct sockaddr_in serverAddr;
    int socket_fd=-1;
    
    bzero(&clientAddr, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_addr.s_addr = htons(INADDR_ANY);
    clientAddr.sin_port = htons(0);
    //创建client
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0) {
        fprintf(stderr, "initial tcp_client create socket failed\n");
        return -1;
    }
    // 3.将socket建立为非阻塞,此时socket被设置为非阻塞模式
    int flags = fcntl(socket_fd, F_GETFL, 0);       //获取建立的sockfd的当前状态(非阻塞)
    fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);  //将当前sockfd设置为非阻塞
    if (bind(socket_fd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) == -1) {
        fprintf(stderr, "initial tcp_client bind socket failed\n");
        return -1;
    }
    bzero(&serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(tcp_server_ip);
    serverAddr.sin_port = htons(tcp_server_port);
    if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {
    	fprintf(stderr, "connet to server failed\n");
    	return -1;
    }

详细使用方法参照

发布了8 篇原创文章 · 获赞 8 · 访问量 251

猜你喜欢

转载自blog.csdn.net/whuer_xiaojie/article/details/105161195