首页 > 技术文章 > Linux 套接字socket的关联地址和连接详解

zzzPark 2017-02-15 12:03 原文

#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一起用的。

 

推荐阅读