socket通信 bind() 函数详解
一.函数解释
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 Example:./server 5005 "); 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)已连接。 ",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 ",iret); break; } printf("接收:%s ",buffer); strcpy(buffer,"ok"); if ( (iret=send(clientfd,buffer,strlen(buffer),0))<=0) // 向客户端发送响应结果。 { perror("send"); break; } printf("发送:%s ",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);
上一篇:
Java架构师技术进阶路线图
下一篇:
burpsuite安装步骤(带下载链接)