socket.bind()_socket()函数[通俗易懂]

socket.bind()_socket()函数[通俗易懂]一.函数解释1.函数的作用:  服务端用于将把用于通信的地址和端口绑定到socket上

一.函数解释

在这里插入图片描述

1.函数的作用:

  服务端用于将把用于通信的地址和端口绑定到 socket 上。所以可以猜出,这个函数的参数应该包含:用于通信的 socket 和服务端的 IP 地址和端口号。ip地址和端口号是放在 socketaddr_in 结构体里面的。

2.函数的声明:

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

  (1)参数 sockfd ,需要绑定的socket。

  (2)参数 addr ,存放了服务端用于通信的地址和端口。

  (3)参数 addrlen ,表示 addr 结构体的大小

  (4)返回值:成功则返回0 ,失败返回-1,错误原因存于 errno 中。如果绑定的地址错误,或者端口已被占用,bind 函数一定会报错,否则一般不会返回错误。

3.服务端示例代码

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
int main(int argc,char *argv[])
{ 
   
  if (argc!=2)
  { 
   
    printf("Using:./server port\nExample:./server 5005\n\n"); return -1;
  }
 
  // 第1步:创建服务端的socket。
  int listenfd;
  if ( (listenfd = socket(AF_INET,SOCK_STREAM,0))==-1) { 
    perror("socket"); return -1; }
 
  // 第2步:把服务端用于通信的地址和端口绑定到socket上。
  struct sockaddr_in servaddr;    // 服务端地址信息的数据结构。
  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family = AF_INET;  // 协议族,在socket编程中只能是AF_INET。
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);          // 任意ip地址。
  //servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 指定ip地址。
  servaddr.sin_port = htons(atoi(argv[1]));  // 指定通信端口。
  if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
  { 
    perror("bind"); close(listenfd); return -1; }
 
  // 第3步:把socket设置为监听模式。
  if (listen(listenfd,5) != 0 ) { 
    perror("listen"); close(listenfd); return -1; }
 
  // 第4步:接受客户端的连接。
  int  clientfd;                  // 客户端的socket。
  int  socklen=sizeof(struct sockaddr_in); // struct sockaddr_in的大小
  struct sockaddr_in clientaddr;  // 客户端的地址信息。
  clientfd=accept(listenfd,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);
  printf("客户端(%s)已连接。\n",inet_ntoa(clientaddr.sin_addr));
 
  // 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
  char buffer[1024];
  while (1)
  { 
   
    int iret;
    memset(buffer,0,sizeof(buffer));
    if ( (iret=recv(clientfd,buffer,sizeof(buffer),0))<=0) // 接收客户端的请求报文。
    { 
   
       printf("iret=%d\n",iret); break;  
    }
    printf("接收:%s\n",buffer);
 
    strcpy(buffer,"ok");
    if ( (iret=send(clientfd,buffer,strlen(buffer),0))<=0) // 向客户端发送响应结果。
    { 
    perror("send"); break; }
    printf("发送:%s\n",buffer);
  }
 
  // 第6步:关闭socket,释放资源。
  close(listenfd); close(clientfd);
}

二.端口问题

  1.端口用了一次,还没有释放再用这个端口,出现被占用的情况。
在这里插入图片描述

  (1)使用5002端口没有释放
在这里插入图片描述
  (2)再使用一次5002端口,提示端口已经被占用
在这里插入图片描述

  2.socket网络编程中,用于监听的端口范围是多少?默认的端口范围是 0-65535

  (1)1024以下的端口 (是系统保留的),普通用户没有权限。root用户可以
在这里插入图片描述

  (2)1024(包括1024)以上的端口,都可以使用
在这里插入图片描述

三.服务端 socket 的 SO_REUSEADDE 属性

  1.服务端程序的端口释放后可能会处于 TIME_WAIT 状态(等待),要等待两分钟后才能被再次使用,

解决方法:设置 SO_REUSEADDE 选项,让端口释放后立即可以被再次使用。

  2.设置 SO_REUSEADDE 选项,把这段代码写入服务端程序。

int opt = 1; unsigned int len = sizeof(opt);
setsockopt(listenfd,SOL_SOCKET,REUSEADDR,&opt,len);

在这里插入图片描述

今天的文章socket.bind()_socket()函数[通俗易懂]分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/72227.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注