当前位置: 首页 > news >正文

网络编程接口bind学习

1、概述

下面2个问题你会怎么回答呢?

1、bind如果绑定0号端口,可以工作么,如果能正常工作,绑定的什么端口
2、客户端可以调用bind么

2、解析

2.1、bind如果绑定0号端口,可以工作么,如果能正常工作,绑定的什么端口

是可以工作的;当使用bind绑定0号端口时,系统会自动选择一个未被占用的临时端口,通常从32768~60999范围内选择。如果程序显示指定非0端口进行绑定,则使用指定端口监听。
例如:select_server程序绑定0号端口,俩次运行分别被分配了34359、43959端口

2.2、客户端可以调用bind么

可以调用bind,并没有规定只有服务端使用bind。

客户端连接服务器,若未显示调用bind,系统会自动为其分配一个临时端口。
客户端连接服务器,若显示调用bind,会使用指定端口和服务端通信。
例如:

1、用nc命令模仿客户端,没有调用bind绑定端口,连接select_server

2、用nc命令模仿客户端,显示调用bind绑定端口,连接select_server

2.3、原理

socket由2部分组成

1、文件描述符fd(int型)

2、内核对象:tcb(包含源ip、源端口号、目标ip、目标端口、协议等信息)

文件描述符fd 和 tcb一一对应

bind作用:通过fd找到内核对象tcb,设置ip、port

2.4、select_server代码

有需要可以下载代码,自己本地编译试试

编译:gcc -o select_server select_main.c

#define _GNU_SOURCE#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <arpa/inet.h>#define INVALID_HANDLE_VALUE (-1)
#define LISTEN_BACKLOG (1024)int main()
{int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);if(sockfd == INVALID_HANDLE_VALUE){perror("socket creation failed");return -1;}int opt = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));// 绑定struct sockaddr_in servAddr;servAddr.sin_family = AF_INET;// servAddr.sin_addr.s_addr = inet_addr("192.168.202.223");servAddr.sin_addr.s_addr = htonl(INADDR_ANY);servAddr.sin_port = htons(0);if(-1 == bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr))){perror("bind error");close(sockfd);return -1;}// 监听if(-1 == listen(sockfd, LISTEN_BACKLOG)){perror("listen error");close(sockfd);return -1;}// 获取监听端口struct sockaddr_in bound_addr;socklen_t len = sizeof(bound_addr);if(getsockname(sockfd, (struct sockaddr*)&bound_addr, &len) == 0){printf("server bound port:%d\n", ntohs(bound_addr.sin_port));}else{printf("getsockname failed\n");}// select模型int maxfd = sockfd;fd_set rfds, temp_fds;FD_ZERO(&rfds);FD_SET(sockfd, &rfds);while(1){temp_fds = rfds;int nready = select(maxfd + 1, &temp_fds, NULL, NULL, NULL);if(nready < 0 && errno != EINTR){break;}// 检查新连接if(FD_ISSET(sockfd, &temp_fds)){struct sockaddr_in client_addr;socklen_t addrlen = sizeof(client_addr);int client_fd = accept4(sockfd, (struct sockaddr*)&client_addr, &addrlen, SOCK_NONBLOCK);if(client_fd < 0){if(errno == EAGAIN || errno == EWOULDBLOCK){printf("Error %s\n", strerror(errno));}else{printf("accept4 failed %s\n", strerror(errno));}}else{if(client_fd > maxfd){maxfd = client_fd;}FD_SET(client_fd, &rfds);    // 打印客户端信息printf("client fd:%d ip:%s port:%d\n", client_fd,  inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));}}// 检查已连接的客户端是否有数据for(int sock_client = sockfd + 1; sock_client <= maxfd; ++sock_client){if(FD_ISSET(sock_client, &temp_fds)){char buf[1024] = {0};int n = recv(sock_client, buf, sizeof(buf), 0);if( n < 0){// 发生错误,判断errno是否为EAGAIN EWOULDBLOCKif(errno != EAGAIN && errno != EWOULDBLOCK){printf("Client on fd %d disconnected\n", sock_client);FD_CLR(sock_client, &rfds);close(sock_client);}}else if (n == 0){// 对端关闭FD_CLR(sock_client, &rfds);close(sock_client);continue;}else{// 收到数据buf[n] = '\0';printf("recv data:%s\n", buf);send(sock_client, buf, n, 0);}}}}// 关闭套接字for(int i = sockfd; i <= maxfd; ++i){close(i);}return 0;
}

学习链接:https://github.com/0voice

http://www.dtcms.com/a/309735.html

相关文章:

  • HTTPS的工作原理
  • 微信小程序服务器配置指南:从入门到高可用架构的腾讯云方案
  • CS231n-2017 Lecture8深度学习框架笔记
  • linux编译基础知识-编译时路径和运行时路径
  • 基于python实现的高效文件压缩工具:Zstandard、LZ4、Brotli 一站式解决方案
  • wsl配置文件(wsl: 检测到 localhost 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支 持 localhost 代理。)
  • 世代距离(GD)和反转世代距离(IGD)详析
  • Python入门Day14:面向对象编程初步(OOP入门)
  • 国内短剧CPS系统开发:技术架构与商业化实践
  • 离线智能破局,架构创新突围:RockAI与中国AI的“另一条车道”
  • MySQL CPU占用过高排查指南
  • 动作捕捉技术重塑具身智能开发:高效训练与精准控制的新范式
  • k8s之NDS解析到Ingress服务暴露
  • vscode cursor配置php的debug,docker里面debug
  • 嵌入式学习的第四十天-51单片机
  • Vue模板语法详解:从基础到进阶的响应式绑定指南2
  • 【AI论文】大语言模型量化的几何原理:将GPTQ视为Babai最近平面算法
  • 开发者体验如何度量?
  • springboot在线法律服务平台-计算机毕业设计源码45635
  • Context API
  • Class29ResNet
  • 机器学习——逻辑回归(LogisticRegression)的核心参数:以约会数据集为例
  • 数智管理学(四十三)
  • Python LRU缓存应用与示例
  • C++拷贝构造函数
  • rhcsa笔记大全
  • 【2025/08/01】GitHub 今日热门项目
  • PendingIntent的flag和原理解析
  • 【Halcon 】Halcon 实战:如何为 XLD 模板添加极性信息以提升匹配精度?
  • Linux系统编程Day3-- Linux常用操作(续)