bind函数和accept函数使用中的常见坑解析

首先先看这两个函数:

bind():

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 第一个参数sockfd使用的应该是服务器端的socket文件描述符。
  • 第二个参数const struct sockaddr *addr是构造出的IP地址和端口号。
  • 第三个参数是addr的长度。
  • bind函数的返回值为“0”则创建成功。失败返回-1,设置errno。

accept():

#include <sys/types.h> 		/* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 第一个参数sockfd同bind也是服务器端的socket文件描述符。
  • 第二个参数addr是传出参数,返回链接客户端的地址信息,其中包含IP地址和端口号。
  • 第三个参数addrlen是一个传入传出参数,传入的,是sizeof(addr)的大小函数在返回时,则返回的是真正接收到地址结构体的大小
  • accept函数的返回值则是创建结果,如果创建成功,返回的是新的客户端的socket文件描述符,用于和客户端通信,创建失败则返回-1,设置errno。

这里需要注意的是:

一、sockaddr的问题

   在两个函数中,都是使用了struct sockaddr类型的参数。这个结构体的定义为:

struct sockaddr {
    sa_family_t sa_family;            //16位的地址类型
    char sa_data[14];                 //14字节的地址数据
};

    但是在现代编程中sockaddr类型已经被废弃,取而代之的是struct sockaddr_in,定义为:

struct sockaddr_in {
	__kernel_sa_family_t sin_family; 			/* Address family */  	地址结构类型
	__be16 sin_port;					 /* Port number */		端口号
	struct in_addr sin_addr;					/* Internet address */	IP地址
	/* Pad to size of `struct sockaddr'. */
	unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
	sizeof(unsigned short int) - sizeof(struct in_addr)];
};

    所以,我们需要在编程的过程中,使用scokaddr_in来传值,然后,在后续传参的时候,把sockaddr_in强制转换成sockaddr来使用。

    比如:

struct sockaddr_in serv_addr;

serv_addr.sin_family = AF_INET;  						
serv_addr.sin_port = htons(SERV_PORT);						
serv_addr.sin_addr.s_addr= htonl(INADDR_ANY);				

bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

cfd=accept(lfd,(struct sockaddr *)&clie_addr,&clie_addr_len);

 

二、传入传出参数的问题:

通过观察bind和accept函数的参数,可以发现:

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

两个函数的定义中第三个参数,一个是socklen_t addrlen,一个是socklen_t *addrlen。

bind函数中soclen_t addr表示这是一个传入参数,在使用的时候,可以像上文的程序中一样,直接sizeof(serv_addr)传值进去。

accpet函数中socklen_t *addr表示:这是一个传入传出参数,在使用的时候,必须先在socklen中声明之后,才可以使用。在accpet函数返回的时候,*addr也会被重新赋值。

 

总结一下传入传出参数的使用:

  • 传入的参数,需要在传入之前,先初始化好一个实际值
  • 传出的参数,要加“&”取地址。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值