linux 套接字 linux用户权限

Linux 进程间套接字通信(Socket)基础知识

姓名:罗学元  学号:21181214375  学院:广州研究院

【嵌牛导读】Linux进程间套接字通信基础

【嵌牛鼻子】Linux进程间套接字及通信介绍

【嵌牛提问】Linux进程间套接字包含哪些内容,如何实现通信

一、套接字(Socket)通信原理

套接字通信允许互联的位于不同计算机上的进程之间实现通信功能。

二、套接字的属性

套接字的特性由3个属性确定,它们分别是:域、类型和协议。

1.套接字的域

它指定套接字通信中使用的网络介质,最常见的套接字域是AF_INET,它指的是Internet网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的IP地址和端口来指定一台联网机器上的某个特定服务,所以在使用socket作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。

另一个域AF_UNIX表示UNIX文件系统,就是文件输入/输出,它的地址就是文件名。

2.套接字类型

因特网提供了两种通信机制:流(stream)和数据报(datagram),因而套接字的类型也就分为流套接字和数据报套接字。我们主要看流套接字。

流套接字由类型SOCK_STREAM指定,它们是在AF_INET域中通过TCP/IP连接实现,同时也是AF_UNIX中常用的套接字类型。

流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。

与流套接字相对的是由类型SOCK_DGRAM指定的数据报套接字,它不需要建立连接和维持一个连接,它们在AF_INET中通常是通过UDP/IP实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高,因为它并不需要总是要建立和维持一个连接。

3.套接字协议

只要底层的传输机制允许不止一个协议来提供要求的套接字类型,我们就可以为套接字选择一个特定的协议。通常只需要使用默认值。

三、套接字地址

每个套接字都有其自己的地址格式,对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件

struct sockaddr_un{

sa_family_t sun_family; //AF_UNIX,它是一个短整型

char sum_path[]; //路径名

};

对于AF_INET域套接字来说,它的地址结构由sockaddr_in来描述,它至少包括以下几个成员:

struct sockaddr_in{

short int sin_family; //AN_INET

unsigned short int sin_port; //端口号

struct in_addr sin_addr;  //IP地址

}

而in_addr被定义为:

struct in_addr{

unsigned long int s_addr;

}

四、基于流套接字的客户/服务器的工作流程

使用socket进行进程通信的进程采用的客户/服务器系统是如何工作的呢?

1.服务器端

首先,服务器应用程序用系统调用socket来创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,它不能与其他的进程共享。

接下来,服务器进程会给套接字起个名字,我们使用系统调用bind来给套接字命名。然后服务器进程就开始等待客户连接到这个套接字。

然后,系统调用listen来创建一个队列,并将其用于存放来自客户的进入连接。

最后,服务器通过系统调用accept来接受客户的连接。它会创建一个与原有的命名套接不同的新套接字,这个套接字只用于与这个特定客户端进行通信,而命名套接字(即原先的套接字)则被保留下来继续处理来自其他客户的连接。

2.客户端

基于socket的客户端比服务器端简单。同样,客户应用程序首先调用socket来创建一个未命名的套接字,然后讲服务器的命名套接字作为一个地址来调用connect与服务器建立连接。

一旦连接建立,我们就可以像使用底层的文件描述符那样用套接字来实现双向数据的通信。

详解Linux内核网络编程技术,原始套接字编程是如何实现的

原始套接字编程详解,解析如何在Linux内核中实现自定义数据包发送与接收。

原始套接字编程与UDP编程类似,主要涉及创建套接字后通过该套接字接收或发送数据。其特殊之处在于原始套接字允许开发者自行组装数据包,包括伪装本地IP与MAC地址,并且能够接收本机网络卡上的所有数据帧,但此功能需在管理员权限下使用。

创建原始套接字使用函数`socket(int family, int type, int protocol)`。成功创建后返回链路层的套接字,失败则返回负数。

接下来,我们探讨原始套接字的高级应用。混杂模式允许网卡接收所有经过网络卡的数据流,不论其目的地是否为该卡。这一模式在网络故障诊断和数据窃听中具有重要应用,需在管理员权限下设置。Linux与Windows操作系统均有混杂模式抓包工具,如Wireshark。

在Linux中,通过命令`ifconfig eth0 promisc`启用混杂模式,而`ifconfig eth0-promisc`则用于取消。代码实现混杂模式设置如下:

原始套接字编程还涉及自定义数据包的发送。发送函数通过参数接收数据包内容,并返回实际发送的数据长度。此外,为了在Linux中定义本地网络接口,通常需包含特定头文件。

以下是一个发送完整代码示例:

cpp

#include socket.h>

#include in.h>

#include inet.h>

int main(){

int sock= socket(AF_PACKET, SOCK_RAW, htons(0x0003));

struct sockaddr_ll addr={.sll_family= AF_PACKET,.sll_ifindex= IF_INDEX_OF_YOUR_NETWORK_INTERFACE};

char data[]="Your custom data packet here";

int sent= sendto(sock, data, strlen(data), 0,(struct sockaddr*)&addr, sizeof(addr));

close(sock);

return sent;

}

此示例中,`AF_PACKET`和`SOCK_RAW`参数指定使用链路层协议进行数据包发送,`htons(0x0003)`表示使用以太网协议。`sendto`函数用于发送自定义数据包。

在学习原始套接字编程时,深入理解其功能与实现细节至关重要。此外,加入Linux内核技术交流群,如【865977150】,获取更多学习资源,包括书籍、视频资料,能够显著提升学习效率与实践能力。

通过本文的详细解析,希望您能够更好地理解和掌握原始套接字编程在Linux内核网络编程中的应用。

【linux】多个套接字可以绑定同一个端口吗

在日常开发中,端口冲突问题经常出现。然而,是否所有进程都不能同时监听同一个端口?让我们深入了解 SO_REUSEPORT选项。

SO_REUSEPORT是 Linux内核从 3.9版本起引入的一种新 socket选项,允许多个套接字绑定到同一个 IP和端口。它主要针对多核 CPU性能的发挥,改进了多进程处理网络请求的方式。

常见的多进程网络请求处理模式有两种:主进程绑定套接字并 fork子进程,子进程通过 accept和 epoll_wait处理请求(Nginx的默认模式)。然而,这种模式会导致著名的“惊群”问题,即多个进程同时监听同一套接字时,网络事件发生后所有进程被唤醒,只有其中一个可以处理事件,其他进程无效。

惊群问题会导致 CPU资源浪费和锁竞争开销。在早期 Linux内核版本中,多个进程 accept同一 socket会出现惊群问题。但通过引入 WQ_FLAG_EXCLUSIVE选项,Linux 2.6内核版本解决了这一问题。高性能服务现在多采用 epoll方案,它同样存在惊群现象。

在 epoll惊群问题中,父进程 bind、listen后 fork出子进程,子进程通过 epoll_wait等待事件,导致事件发生时所有子进程同时被唤醒。解决这一问题较为简便的方式是使用 SO_REUSEPORT选项。

SO_REUSEPORT原理包括在内核为处于 LISTEN状态的 socket分配 32个哈希桶,根据端口号哈希打散并解决冲突。当收到 SYN握手报文时,查找得分最高的 socket处理请求。在特定内核版本中,引入 SO_REUSEPORT group概念,优化查找过程。

SO_REUSEPORT在安全性方面考虑如下两点:只有第一个启用 SO_REUSEPORT的进程可以绑定相同端口,后续进程需与之有相同有效用户 ID才能绑定。

SO_REUSEPORT带来的好处包括内核级负载均衡和滚动升级简化。虽然原理较为复杂,但它解决了惊群问题,提高了网络处理效率。

阅读剩余
THE END