Linux 套接字socket的关联地址和连接详解
#include<sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t len);
这个函数往往用在服务进程上!
举个例子
#include "unp.h"
#include <time.h>
int main(int argc,char**argv){
listenfd=Socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
//..给servaddr赋值
Bind(listenfd,(SA*)&servaddr,sizeof(servaddr));
Listen(...);
for(;;)
{
.. //write
}
那么让服务进程的套接字listensock 绑定在服务器的地址上。并且地址端口号需小于1024。
接下来介绍两个函数
#include<sys/socket.h>
int getsockname(int sockfd,struct sockaddr *addr,socklen_t alenp);
//用来发现绑定在sockfd上的地址
int getpeername(int sockfd,struct sockaddr *addr,socklen_t alenp);
//如果sockfd 与对方已经连接可以用来发现对方地址
sockfd 就是套接字
addr 通常是一个空的addr结构
alenp 是一个整数指针,整数是addr结构长度
而对于客户端呢?
在与服务器交换数据前需要先建立一个连接。这就是connect函数的用处!
#include<sys/socket.h>
int connect(int sockfd,const struct *sockaddr,socklen_t len)
sockaddr 是想与之通信的服务器地址,connect会给sockfd绑定默认地址。举个例子:
#include "unp"
int main(char argc,char** argv){
//声明各种变量
sockfd=socket(AF_INET6,SOCK_STREAM,0)
//给servaddr各种赋值
connet(sockfd,(SA*)&sockaddr,sizeof(servaddr));
while(...)
{
//read
}
当然使用connect函数时肯定会经常发生错误。所以真正重要的是如何应对connect函数的错误!
而且往往错误是不可避免的。
1 有可能服务器没开!
2 服务器的等待连接队列已经满了!
#include “aupe.h"
#include<sys/scoket.h>
#define MAXSLEEP 128
int connect_retry(int domain,int type,int protocol,const struct *addr,socklen_t alen){
int numsec,fd;
for(numsec=1;numsec<=MAXSLEEP;numsec<<=1)
{ if(fd=sock(domain,type,protocol))<0)return -1;
if(connect(fd,addr,alen)==0){
...
return fd);}
close(fd);
if(numsec<MAXSLEEP/2) sleep(numsec);
}
return -1;
}
这一段代码有两个要点:
1指数补偿
如果connect失败后 进程会休眠并再下一次循环再尝试连接。但每次休眠时间会指数增加。
直到超过最长延迟时间为止!
2考虑到了兼容性设计
在有一些操作系统中一旦connect失败后 sockfd 会失效。所以如果不重新声明一个新的 sockfd而用重用旧的!
就会导致不断重连失败!
还有一些比较深奥的问题,比如套接字处于非阻塞模式会出现什么状况!就不讨论了
connect 函数其实可以和SCOK_DGRAM一起用的。