socket编程之bind()函数使用示例详解

目录
  • 正文
  • 端口号具体是怎么绑定
    • 老代码
    • 端口被占用的问题解决

正文

当你创建了socket之后,你会想要把这个socket和你本机上的某个端口号(port)进行关联。

端口号是内核用来确认将收到的数据包交给哪个具体进程的socket descriptor的依据。

通常在写服务端程序的时候我们才需要进行关联,客户端程序不需要我们手动绑定端口,直接connect()就好了。

端口号具体是怎么绑定

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

sockfdsocket()返回的一个socket file descriptormy_addr是一个指向包含了你的端口号和IP地址信息的struct sockaddr指针;addrlen是以字节为单位的地址长度。

接下来,我们给出一个例子,它将socket和我本机的3490端口进行绑定:

struct addrinfo hints, *res;
int sockfd;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
getaddrinfo(NULL, "3490", &hints, &res);
// make a socket:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
// bind it to the port we passed in to getaddrinfo():
bind(sockfd, res->ai_addr, res->ai_addrlen);

通过使用AI_PASSIVE标识,程序会自动绑定它所在的程序的IP。如果你想精确绑定到本机的某一个IP地址,你就不能用AI_PASSIVE了,而且你还得把getaddrinfo()的第一个参数从NULL改为你想绑定的那个IP地址。

bind()和其他系统调用一样,发生错误的时候返回-1,并且会设置全局变量errno的值。

很多老代码都会在调用bind()之前手动封装 struct sockaddr_in 。当然,这里绑定的肯定是IPv4的地址,如果你想使用IPv6,你照样可以手动封装struct sockaddr_in6 ,但是极力不推荐你这么做。你还是应该老老实实用 getaddrinfo() ,这样更优雅、更简单。

老代码

// !!! THIS IS THE OLD WAY !!!
int sockfd;
struct sockaddr_in my_addr;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);     // short, network byte order
my_addr.sin_addr.s_addr = inet_addr("10.12.110.57");
memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr);

上面这个代码中,你依然可以把my_addr.sin_addr.s_addr设置为 INADDR_ANY ,它的作用上文提到的AI_PASSIVE一样,都会让代码自动绑定到本机IP。 INADDR_ANY 的IPv6版本是一个全局变量,叫in6addr_any,这个变量会被指定给你的 struct sockaddr_in6sin6_addr字段。

你也可以使用IN6ADDR_ANY_INIT这个宏来初始化变量

调用bind()时有一件事需要你特别注意:不要使用1024以下的端口号,因为这些端口号是被保留使用的,除非你是超级管理员。除了1024以下的,1025~65535之间的随便用(其他程序占用的除外)。

有时候,你明明重新运行了你的服务端程序,但是bind()报错了,提示你“Address already in use”。这是为什么?理论上重启之后端口就会被释放啊!好吧,这是因为有一些连接到socket的连接还悬在内核中,就是它们占用了这个端口号。

端口被占用的问题解决

你可以等一分钟左右让它们自行消失,或者在你的代码加这么几行:

int yes=1;
//char yes='1'; // Solaris people use this
// lose the pesky "Address already in use" error message
if (setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof yes) == -1) {
    perror("setsockopt");
    exit(1);
}

这样就不会再出现端口被占用的问题了。

以上就是socket编程之bind()函数使用示例详解的详细内容,更多关于socket编程bind函数的资料请关注我们其它相关文章!

(0)

相关推荐

  • react使用websocket实时通信方式

    目录 使用websocket实时通信 创建公共组件 在react组件中的使用 websocket在不同情形下的使用 1.在react中使用websocket 2.websocket在小程序中使用 使用websocket实时通信 在react中使用websocket不需要引入其他库,只需要创建一个公共组件,封装一下websocket 创建公共组件 websocket.js let websocket, lockReconnect = false; let createWebSocket = (ur

  • C#使用WebSocket与网页实时通信的实现示例

    目的:使用Fleck框架实现网页与服务端实时通信 传统的网站采用http方式与服务端通信,属于请求响应模式,如何让网页与服务器之间能使用TCP这种双向通信方式实时交流,答案就是使用WebSocket技术. Fleck框架的安装方式: 1.使用NuGet包管理工具安装 Install-Package Fleck -Version 1.2.0 2.下载Fleck源码并编译程序集供服务端引用 github地址:https://github.com/statianzo/Fleck/archive/ref

  • SpringBoot+WebSocket实现消息推送功能

    目录 背景 WebSocket简介 协议原理 WebSocket与HTTP协议的区别 WebSocket特点 应用场景 系统集成Websocket jar包引入 Websocket配置 具体实现 测试示例 页面请求websocket 测试效果 背景 项目中经常会用到消息推送功能,关于推送技术的实现,我们通常会联想到轮询.comet长连接技术,虽然这些技术能够实现,但是需要反复连接,对于服务资源消耗过大,随着技术的发展,HtML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够

  • C++用winapi socket实现局域网语音通话功能

    目录 一.socket通信 二.waveIn和WaveOut的Win32API 1.音频设备的的信息获取 2.音频设备的初始化 3.输入输出设备缓冲区的准备和添加 4.播放和录音的开始和终止 5.录音通知消息的获取和处理 6.关闭音频输入和输出设备 三.通信数据包的设计以及客户端服务器逻辑 前几天看书了解了语音通话的原理,就很想自己尝试一下,然后就——做出来了,嘻嘻,先看看效果吧! 因为这边没办法上传视频,所以只能录制一个gif大家看一下效果,但是是可以听到声音的. 源码下载链接:http://

  • 在Asp.net core项目中使用WebSocket

    今天小试了一下在Asp.net core中使用websocket,这里记录一下: 在 Startup 类的 Configure 方法中添加 WebSocket 中间件. app.UseWebSockets(); 它也可以传入一些参数 app.UseWebSockets(new WebSocketOptions() { KeepAliveInterval = TimeSpan.FromSeconds(120), ReceiveBufferSize = 4 * 1024 }); 添加WebSocke

  • C++ Thread实现简单的socket多线程通信

    目录 起因 服务端 ROS客户端 普通客户端 运行效果 不足 起因 为什么要用C++的Thread,很简单,因为我菜 一打五用pthread实现了socket多线程通信,我之前学并发的时候没看pthread,因此代码只能看个大概,后面还是要系统学一下pthread的 服务端 多线程功能放在腾讯云服务器上,代码如下: #include "tcpserver.h" #include <thread> #include <mutex> TcpServer server

  • socket编程之bind()函数使用示例详解

    目录 正文 端口号具体是怎么绑定 老代码 端口被占用的问题解决 正文 当你创建了socket之后,你会想要把这个socket和你本机上的某个端口号(port)进行关联. 端口号是内核用来确认将收到的数据包交给哪个具体进程的socket descriptor的依据. 通常在写服务端程序的时候我们才需要进行关联,客户端程序不需要我们手动绑定端口,直接connect()就好了. 端口号具体是怎么绑定 #include <sys/types.h> #include <sys/socket.h&g

  • go语言编程之select信道处理示例详解

    目录 select信道处理 fibonacci数列监听 select监听协程 select信道处理 注意:有default就不会阻塞 package main func main() { var chan1 = make(chan int) var chan2 = make(chan int) select { case <-chan1: // 如果chan1成功读到数据,则进行该case处理语句 case chan2: // 如果chan2成功读到数据,则进行该case处理语句 default

  • Java并发编程之Semaphore(信号量)详解及实例

    Java并发编程之Semaphore(信号量)详解及实例 概述 通常情况下,可能有多个线程同时访问数目很少的资源,如客户端建立了若干个线程同时访问同一数据库,这势必会造成服务端资源被耗尽的地步,那么怎样能够有效的来控制不可预知的接入量呢?及在同一时刻只能获得指定数目的数据库连接,在JDK1.5 java.util.concurrent 包中引入了Semaphore(信号量),信号量是在简单上锁的基础上实现的,相当于能令线程安全执行,并初始化为可用资源个数的计数器,通常用于限制可以访问某些资源(物

  • python模块shutil函数应用示例详解教程

    目录 本文大纲 知识串讲 1)模块导入 2)复制文件 3)复制文件夹 4)移动文件或文件夹 5)删除文件夹(慎用) 6)创建和解压压缩包 本文大纲 os模块是Python标准库中一个重要的模块,里面提供了对目录和文件的一般常用操作.而Python另外一个标准库--shutil库,它作为os模块的补充,提供了复制.移动.删除.压缩.解压等操作,这些 os 模块中一般是没有提供的.但是需要注意的是:shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile这两个模块来进行的. 知识串

  • JavaScript异步编程之Promise的初步使用详解

    1. 概述 Promise对象是ES6提出的的异步编程的规范.说到异步编程,就不得不说说同步和异步这两个概念. 从字面意思理解同步编程的话,似乎指的是两个任务同步运行,如果这样理解就错了(至少笔者再没有接触到这个概念的时候有这种误解).同步和异步指的是代码指定执行的顺序(结构化编程范式的执行顺序总是由上至下,由前往后的),如果执行的顺序与代码的相同,就是同步:如果不同,就是异步. 最初,操作系统都是基于命令行的,所有的的语言设计出来也天然是同步的语句,在这种情况下,也不需要异步编程.但是很快,图

  • android编程之XML文件解析方法详解(附源码)

    本文实例讲述了android编程之XML文件解析方法.分享给大家供大家参考,具体如下: 在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结. 今天解析的xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8

  • Python编程之string相关操作实例详解

    本文实例讲述了Python编程之string相关操作.分享给大家供大家参考,具体如下: #coding=utf8 ''''' 字符串是Python中最常见的类型.可以通过引号见包含字符的方式创建. Python里面单引号和双引号的作用是相同的. 字符串是不可变类型,就是说改变一个字符串的元素需要新建一个新的字符串. 字符串是由独立的字符组成,并且这些字符可以通过切片操作顺序地访问. ''' class StringClass(object): ''''' 创建一个字符串就像使用一个标量一样简单.

  • Java Swing组件编程之JTable表格用法实例详解

    本文实例讲述了Java Swing组件编程之JTable表格用法.分享给大家供大家参考,具体如下: 表格是GUI编程中使用较多,但也是最麻烦的一个控件之一.表格是用来显示二维数据,提供编辑,选择等功能.如果只是显示数据,这还是非常easy的,只要在JTable中传入二维数组或集合就可以了. 示例1: package awtDemo; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTab

  • php安全攻防世界unserialize函数反序列化示例详解

    目录 步骤 总结 步骤 首先打开题目,发现给了一段源码: 分析源码,发现类里面有三个魔术方法: __construct():构造函数,对类的变量进行初始化,创建时自动调用,用得到的参数覆盖$file __destruct():销毁时调用,会显示文件的代码,这里要显示fl4g.php __wakeup():在进行反序列化之前会调用,会把$file重置成index.php 正则表达式的含义:o或c开头,冒号,一个或多个数字,不区分大小写 ok,分析完毕:我们要将序列化后的字符串进行base64加密之

  • Go并发编程之sync.Once使用实例详解

    目录 一.序 二. 源码分析 2.1结构体 2.2 接口 三. 使用场景案例 3.1 单例模式 3.2 加载配置文件示例 四.总结 五. 参考 一.序 单从库名大概就能猜出其作用.sync.Once使用起来很简单, 下面是一个简单的使用案例 package main import ( "fmt" "sync" ) func main() { var ( once sync.Once wg sync.WaitGroup ) for i := 0; i < 10;

随机推荐