Linux下socket bind的原理和使用方法 (socket bind linux)

引言:

在网络编程中,socket编程是非常常见和重要的一种编程方式,它将网络通信变的更加灵活和高效。作为socket的一种基础操作——绑定(bind)的作用非常重要,本文将详细介绍在Linux下,socket bind的原理和使用方法。

一、socket简介

socket(套接字)是指向网络地址空间的一种抽象,它相当于一种可靠的数据流端点。 通过它,我们可以进行网络上的数据交换。socket负责把应用程序的数据发送给网络上的目标主机(包括UDP和TCP) ,或者从网络上的另一台主机接收数据。本篇文章主要讲解在socket编程中bind函数的使用方法。

二、bind函数的原理

bind函数的原理是将一个socket和指定的网络地址进行绑定。在使用bind函数之前首先需要创建一个socket文件描述符。bind函数的调用需要如下两个参数:

bind(int socket_fd, struct sockaddr *addr, socklen_t addr_len)

其中,socket_fd为socket的文件描述符,addr为一个指向地址结构体的指针,addr_len为结构体的长度。调用过后,socket即拥有了地址信息。

三、实例使用

下面我们通过实际的代码来了解在Linux下如何使用bind函数:

1. 创建socket

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

2. 设置端口和地址

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_port = htons(9000);

addr.sin_addr.s_addr = htonl(INADDR_ANY);

3. 绑定地址和端口

bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));

本例中,socket采用的是TCP协议,在设置地址信息的时候,设置了端口和IP地址。其中,htons和htonl是网络字节序和主机字节序之间的转换,INADDR_ANY相当于0.0.0.0,表示绑定本地任意网络接口。

四、常见错误及解决方法

1. EADDRINUSE错误

在进行bind操作时,可能会遇到EADDRINUSE错误,这是因为该地址已被占用。可以通过如下命令找到被占用的端口:

sudo lsof -i:9000

其他解决方法包括释放已占用的端口或修改端口信息。

2. EACCES错误

在进行bind操作时,如果无法申请到指定端口,可能会遇到EACCES错误。这是因为当前用户没有足够的权限进行此操作。解决方法是使用sudo权限重新执行bind操作。

五、

通过本文的介绍,我们了解到了在。在实际应用中,我们需要考虑端口和地址的选择以及错误的处理,希望本文能够对大家理解socket编程和网络通信有所帮助。

相关问题拓展阅读:

linux手册翻译——socket(7)

socket – Linux 套接字接口

本手册页描述了 Linux 网络套接字层用户接口。 套接字是用户进程和内核中网络协议栈之间的统一接口。 协议模块分为协议族(protocol families)(如 AF_INET、AF_IPX 和 AF_PACKET)和套接字类含芹型(socket types)(如 SOCK_STREAM 或 SOCK_DGRAM)。 有关families和types的更多信息,请参阅 socket(2) 。

用户进程使用这些函数来发送或接收数据包以及执行其他套接字操作。 有关更多信息,请参阅它们各自的手册页。

socket(2) 创建套接字,connect(2) 将套接字连接到远程套接字地址,bind(2) 函数将套接字绑定到本地套接字地址,listen(2) 告诉套接字应接受新连接, accept(2) 用于获取具有新传入连接的新套接字。 socketpair(2) 返回两个连接的匿名套接字(仅为少数本地families如 AF_UNIX 实现)

send(2)、sendto(2) 和sendmsg(2) 通过套接字发送数据,而recv(2)、recvfrom(2)、recvmsg(2) 从套接字接收数据。 poll(2) 和 select(2) 等待数据到达或准备好发送数据。 此外,还可以使用 write(2)、writev(2)、sendfile(2)、read(2) 和 readv(2) 等标准 I/O 操作来读取和写入数据。

getsockname(2) 返回本地套接字地址, getpeername(2) 返回远程套接字地址。 getsockopt(2) 和 setsockopt(2) 用于设置或获取套接字层或协议选项。 ioctl(2) 可用于设置或读取一些其他选项。

close(2) 用于关闭套接字。 shutdown(2) 关闭全双工套接字连接的一部分。

套接字不支持使用非零位置查找或调用 pread(2) 或 pwrite(2)。

通过使用 fcntl(2) 在套接字文件描述符上设置 O_NONBLOCK 标志,可以在套接字上执行非阻塞 I/O。 然后所有会阻塞的操作(通常)将返回 EAGAIN(操作应稍后重试); connect(2) 将返回 EINPROGRESS 错误。 然后用户可以通过 poll(2) 或 select(2) 等待各种事件。

如果不使用poll(2) 和 select(2) ,还让内核通过 SIGIO 信号通知应用程序有关事件的信息。 为此,必须通过 fcntl(2) 在套接字文件描述符上设置 O_ASYNC 标志,并且必须通过 sigaction(2) 安装有效的 SIGIO 信号处理程序。 请参阅下面的信号讨论。

每个套接字域(families)都有自己的套接字地址格式,具有特定于域的地址结构。 这些结构的首字段都是整数类型的“家族”字段(类型为 sa_family_t),即指出自己的套接字域或者说是protocol families。 这允许对所有套接字域可以使用统一的系统调用(例如,connect(2)、bind(2)、accept(2)、getsockname(2)、getpeername(2)),并通过套接字地址来确定特定的域。

为了允许将任何类型的套接字地址传递给套接字 API 中的接口,定义了类型 struct sockaddr。 这种类型的目的纯粹是为了允许将特定于域的套接字地址类型转换为“通磨猜用”类型,以避免编译器在调用套接字 API 时发出有关类型不匹配的警告。

struct sockaddr 以及在AF_INET常瞎老型用的地址结构struct sockaddr_in如下所示,sockaddr_in.sin_zero是占位符:

此外,套接字 API 提供了数据类型 struct sockaddr_storage。 这种类型适合容纳所有支持的特定于域的套接字地址结构; 它足够大并且正确对齐。 (特别是它足够大,可以容纳 IPv6 套接字地址。)同struct sockaddr一样,该结构体包括以下字段,可用于标识实际存储在结构体中的套接字地址的类型: sa_family_t ss_family;

sockaddr_storage 结构在必须以通用方式处理套接字地址的程序中很有用(例如,必须同时处理 IPv4 和 IPv6 套接字地址的程序)。

下面列出的套接字选项可以使用setsockopt(2) 设置并使用getsockopt(2) 读取。

当写入已关闭(由本地或远程端)的面向连接的套接字时,SIGPIPE 被发送到写入进程并返回 EPIPE。 当写调用指定 MSG_NOSIGNAL 标志时,不发送信号。

当使用 FIOSETOWN fcntl(2) 或 SIOCSPGRP ioctl(2) 请求时,会在 I/O 事件发生时发送 SIGIO。 可以在信号处理程序中使用 poll(2) 或 select(2) 来找出事件发生在哪个套接字上。 另一种方法(在 Linux 2.2 中)是使用 F_SETSIG fcntl(2) 设置实时信号; 实时信号的处理程序将使用其 siginfo_t 的 si_fd 字段中的文件描述符调用。 有关更多信息,请参阅 fcntl(2)。

在某些情况下(例如,多个进程访问单个套接字),当进程对信号做出反应时,导致 SIGIO 的条件可能已经消失。 如果发生这种情况,进程应该再次等待,因为 Linux 稍后会重新发送信号。

核心套接字网络参数可以通过目录 /proc/sys/net/core/ 中的文件访问。

These operations can be accessed using ioctl(2):

error = ioctl(ip_socket, ioctl_type, &value_result);

Valid fcntl(2) operations:

Linux assumes that half of the send/receive buffer is used for internal kernel structures; thus the values in the corresponding /proc files are twice what can be observed on the wire. Linux will allow port reuse only with the SO_REUSEADDR option when this option was set both in the previous program that performed a bind(2) to the port and in the program that wants to reuse the port. This differs from some implementations (e.g., FreeBSD) where only the later program needs to set the SO_REUSEADDR option. Typically this difference is invisible, since, for example, a server program is designed to always set this option.

LINUX C下ACCEPT失败,前面SOCKET,BIND,LISTEN都成功

应答是要陵岩使用另外一个空的socket对象进行应尺坦御答。而且这个socket对象必须没有被赋值。例信升如下面的程序段;

while (AcceptSock == SOCKET_ERROR)

{

AcceptSock = accept(ConnectSocket,NULL,NULL);

}

我建议 阅读 《unix网络编程》里面有很详细的解释

举个例子:

你可以把socket的IO操作看做是等人

阻塞:

你站在和人越好的地毁念方等人,你们的约定了一个时槐森间,当你等的时间超过了这个时间后你就可以离开这个地点去干其他的事情,否则你将继续在这里等人。而INFINIT就是无限等待下去

非阻塞:

就是你不需要站在越好的地点等人,你可以作在离这个地点很近的纤明困一个咖啡厅喝茶听音乐,但你能够看到这个约定地点的情况,一旦有人来你就可以走过去和那个人见面

阻塞:人来了以后你可以之一时间见到,而不用别人等你

非阻塞:和你正在做的事情有关,如果你在坐在咖啡厅看电视,就很有可能造成别人等你的情况了

看看errno,如果是EAGAIN或EWOULDBLOCK是正常的。

你bupt-is的吧?我也遇到这个问题了,换台电脑就好了

socket bind linux的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于socket bind linux,Linux下socket bind的原理和使用方法,linux手册翻译——socket(7),LINUX C下ACCEPT失败,前面SOCKET,BIND,LISTEN都成功的信息别忘了在本站进行查找喔。


数据运维技术 » Linux下socket bind的原理和使用方法 (socket bind linux)