2.socket;bind;listen;accept;connect;地址复用;客户端服务器回射模型

定义[宏]处理错误

声明:
  #define ERR_EXIT(m) \                                                                                                          
    do  \                                                                                                                        
    { \                                                                                                                          
      perror(m);  \                                                                                                              
      exit(EXIT_FAILURE);  \                                                                                                     
    }while(0);  
调用:
  ERR_EXIT("connect");
1.int socket(int domain, int type, int protocol);
参数:
	domain:指定通信协议族
	type:指定socket类型
		SOCK_STREAM:流式套接字  TCP
		SOCK_DGRAM:数据报套接字  UDP
		SOCK_RAW:原始套接字
	protocol:协议类型
返回值:成功返回非零,即套接字描述字
例:int sockfd=socket(AF_INET,SOCK_STREAM,0);

2.int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
[1]第二个参数struct sockaddr *my_addr获得?
答:通过struct sockaddr_in ----> struct sockaddr,转换而来
 struct sockaddr_in svraddr;  // man 7 ip --->struct sockaddr_in                                                                 
 svraddr.sin_family=AF_INET;                                                                                                    
 svraddr.sin_port=htons(8001);   //htons,不使用htonl                                                                                  
 svraddr.sin_addr.s_addr=INADDR_ANY;//svraddr.sin_addr.s_addr=inet_addr("127.0.0.1"); 
[2]bind如何使用?
答:bind的第二个参数,使用的时候,要进行强制转换
 int ret=bind(sockfd,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));                                                           
 if(ret<0){                                                                                                                     
   perror("bind");                                                                                                              
   exit(1);                                                                                                                     
 }                                                         

3.int listen(int s, int backlog);
参数backlog的含义:指定未完成连接队列的最大长度
  如果一个连接请求到达时,未完成连接队列已满--->客户端的行为分别为:
	[1]客户端将接收到错误ECONNREFUSED.
    [2]如果下层协议支持重发,那么这个连接请求将被忽略,这样客户端在重试的时候就有成功的机会
例:

4.int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
例:
    struct sockaddr_in peeraddr;  //对方的地址信息
    socklen_t peerlen;                                                                                                           
                                                                                                                                 
    int newconn;                                                                                                                 
    if((newconn=accept(sockfd,(struct sockaddr*)&peeraddr,&peerlen))<0){                                                         
      perror("accept");                                                                                                          
      exit(1);                                                                                                                   
    }                                                                                                                            
    printf("new connect:peeraddr=%s, port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));   //打印对方的地址信息

5.int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
例:
  struct sockaddr_in svraddr;                                                   
  svraddr.sin_family=AF_INET;                                                   
  svraddr.sin_port=htons(8001);                                                                                      
  svraddr.sin_addr.s_addr=inet_addr("127.0.0.1"); //svraddr.sin_addr.s_addr=INADDR_ANY;                                    
                                                                                
  int ret=connect(clisock,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));  

6.setsockopt   设置套接字sockfd(文件描述字),可以地址复用
  int optval=1;                                                                                                                  
  setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)); //设置地址复用                                                                                                                                    

客户端服务器回射模型

客户端从键盘上获取数据,发送给服务器
	服务器接收到客户端发送来的数据后,在屏幕上打印输出
	服务器将接收到的数据,原样回射给客户端
客户端接收到服务器回射来的数据后,在屏幕上打印输出

在这里插入图片描述

客户端代码
int main(){                                                                                                                      
  int clisock=socket(AF_INET,SOCK_STREAM,0);                                                                                     
  if(clisock==-1){                                                                                                               
    perror("socket");                                                                                                            
    exit(1);                                                                                                                     
  }                                                                                                                              
  //服务器端的地址:svraddr                                                       
  struct sockaddr_in svraddr;                                                                                                    
  svraddr.sin_family=AF_INET;                                                                                                    
  svraddr.sin_port=htons(8001);                                                                                                  
  //svraddr.sin_addr.s_addr=INADDR_ANY;                                                                                          
  svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");                                                                                
  
  //connect:连接服务器端的地址avraddr                                                                                                                               
  int ret=connect(clisock,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));                                                   
  if(ret<0){                                                                                                                     
    perror("connect");                                                                                                           
    exit(1);                                                                                                                     
  }                                                                                                                              
  printf("svraddr=%s,port=%d",inet_ntoa(svraddr.sin_addr),ntohs(svraddr.sin_port));                                              
                                                                                                                                 
  if(ret==-1){                                                                                                                   
    perror("connect");                                                                                                           
    exit(1);                                                                                                                     
  }                                                                                                                              
                                                                                                                                 
  char sendbuf[1024];                                                                                                            
  char recvbuf[1024];                                                                                                            
  printf("\nsendbuf=");
  while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL){ //从键盘上获取数据
    write(clisock,sendbuf,strlen(sendbuf));  //向服务器发送数据
    int ret=read(clisock,recvbuf,sizeof(recvbuf));  //读取服务器发来的数据
    if(ret>0){                                                                                                                   
      printf("      recvbuf=%s",recvbuf); //fputs(recvbuf,stdout);
    printf("sendbuf=");
    }
    else if(ret==0){ //当read返回0时,证明对方关闭了socket连接
      printf("peer alreadly close");
      close(clisock);
      break;
    }
    else if(ret<0){
      perror("read fail");
      exit(1);
    }
    memset(sendbuf,0,sizeof(sendbuf));
    memset(recvbuf,0,sizeof(recvbuf));
  }
  return 0;
}
服务器代码
int main(){                                                                                                                    
  int sockfd=socket(AF_INET,SOCK_STREAM,0);                                                                                    
  if(sockfd==-1){                                                                                                              
    perror("socket");                                                                                                          
    exit(1);                                                                                                                   
  }                                                                                                                            
                                                                                                                               
  struct sockaddr_in svraddr;  //man 7 ip --->struct sockaddr_in                                                               
  svraddr.sin_family=AF_INET;                                                                                                  
  svraddr.sin_port=htons(8001);//host-->net                                                                                    
  //svraddr.sin_addr.s_addr=INADDR_ANY;                                                                                        
  svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");                                                                              
  int optval=1;                                                                                                                  
  setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)); //设置地址复用                                                                                     
  int ret;                                                                                                                     
  ret=bind(sockfd,(struct sockaddr*)&svraddr,sizeof(struct sockaddr)); //bind                                                  
  if(ret<0){                                                                                                                   
    perror("bind");                                                                                                            
    exit(1);                                                                                                                   
  }                                                                                                                            
  printf("bind...\n");                                                                                                         
                                                                                                                               
  if(listen(sockfd,5)<0){ //listen                           
    perror("listen");                                                                                                          
    exit(1);                                                                                                                   
  }                                                                                                                            
  printf("listen...\n");                                                                                                       
                                                                                                                               
  struct sockaddr_in peeraddr;
  socklen_t peerlen;

  int newconn;
  if((newconn=accept(sockfd,(struct sockaddr*)&peeraddr,&peerlen))<0){ //accept
    perror("accept");                                                                                                          
    exit(1);                                                                                                                   
  }                                                                                                                            
  printf("new connect:peeraddr=%s, port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));                          
                                                                                                                               
  char recvbuf[1024];                                                                                                          
  while(1){                                                                                                                    
    int ret=read(newconn,recvbuf,sizeof(recvbuf)); //读取client发送来的数据                          
    if(ret>0){                                                                                                                 
      printf("recvbuf = %;",recvbuf);                                                                                          
      write(newconn,recvbuf,ret); //将读取的数据,回射给client                          
    }                                                                                                                          
    else if(ret==0){ //read 0 byte--->peer close                                                                               
      printf("peer already close\n");                                                                                          
      close(newconn);                                                                                                          
      break;                                                                                                                   
      //exit(0);                                                                                                               
    }                                                                                                                          
    else if(ret<0){                                                                                                            
      printf("read data fail\n");                                                                                              
      exit(0);                                                                                                                 
    }                                                                                                                          
    memset(recvbuf,0,sizeof(recvbuf));                                                                                         
  }                                                                                                                            
  return 0;                                                                                                                    
}  

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/83110219