您的位置:首页 > 运维架构 > Linux

Linux系统下socket通信注意之bind函数

2015-05-21 22:51 197 查看
一般我们在测试C/S程序的时候,为了方便。一般客户端连接服务器的时候,我们会不注意客户端的ip与端口,我们只关注的是服务器端的ip与端口,这样我们就可以与server通信。

在tcp/ip协议中,我们看到TCP或者UDP数据帧,都含有源地址、源端口与目的地址、目的端口。在socket编程中,创建一个socket句柄,都会有本地的一个IP与端口对应,这个就是源地址与源端口。如果我们在程序中不指定这个源地址与源端口会怎么样呢?这里指定的时候我们采用bind函数进行绑定地址与端口。

如果一个TCP客户端或者服务器没有调用bind进行绑定,因为在调用socket函数创建套接字的时候,内核还没有为套接字分配地址及其端口,当调用connect或者listen函数的时候,内核就要为相应的套接字选择一个临时的端口与地址。

在讨论bind函数之前,需要对网络地址端口格式进行了解:

通用的网络地址标识为sockaddr,为了使不同格式的地址能够传入到套接字函数,地址需要被强制转换成sockaddr类型。其结构如下:

struct sockaddr{
sa_family_t sa_family;
char sa_data[];
......
}
套接字可以实现添加额外成员到sa_data中,Linux中此成员为sa_data[14]。

Internet的地址定义在<netinet/in.h>,在IPV4因特网中(AF_INET)中,套接字的地址结构如下:

struct sockaddr_in{
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
}
struct in_addr{
in_addr_t s_addr;
}
然后bind函数的原型如下:

int bind(int sockfd,const struct sockaddr *addr,socklen_t len);
成功调用返回0,出错返回-1;

下面展示一个客户端绑定本地地址与端口的实例:

/*server ip and port*/
struct sockaddr_in servaddr;
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
servaddr.sin_port = htons(atoi(argv[2]));
/*local ip and port*/
struct sockaddr_in cltaddr;
bzero(&cltaddr,sizeof(cltaddr));
cltaddr.sin_family = AF_INET;
cltaddr.sin_addr.s_addr = inet_addr(argv[3]);
cltaddr.sin_port = htons(atoi(argv[4]));
/*create socket*/
sockfd =socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){
printf("create socket error...\n");
exit(1);
}
int reuse = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
if((bind(sockfd,(struct sockaddr*)&cltaddr,sizeof(cltaddr)))<0){
printf("can not bind....\n");
exit(1);
}
此例子中,cltaddr代表需要绑定的本地地址信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: