linux socket 连接(socket菜鸟教程)

很多朋友对于linux socket 连接和socket菜鸟教程不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!

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 socket的基本操作socket、bind、listen、accept

Linux socket的基本操作涉及到 socket、bind、listen、accept等关键函数。在开始之前,应明确 socket函数的作用类似于普通文件的打开操作,返回一个用于后续读写操作的描述符。创建 socket时,可通过指定参数类型和协议创建不同类型的 socket,但需注意不同类型和协议的组合限制。默认情况下,创建的 socket是主动类型的,后续应通过 bind函数为其绑定特定的地址和端口。bind函数接收地址族、地址和端口作为参数,用于将地址信息赋给 socket。服务器通常在启动时使用 bind函数绑定一个众所周知的地址,以便客户端能连接。而客户端则无需指定地址,系统会自动为其分配端口。在进行 socket操作时,需将主机字节序转换为网络字节序,以确保数据传输的一致性。服务器在调用 listen函数后变为被动监听状态,等待客户端连接请求。客户端调用 connect函数尝试建立连接,服务器通过 accept函数接收请求并建立连接。之后,即可进行网络 I/O操作,类似于普通文件的读写。读写操作可使用 recvmsg()/sendmsg()函数,它们是最通用的 I/O函数,能替代其他 I/O函数。完成操作后,通过 close函数关闭 socket描述符。close操作仅标记 socket为关闭状态,实际关闭需等待引用计数降至零。

Linux中通过Socket文件描述符寻找连接状态介绍

Proc虚拟文件系统下面有许多数字命名的子目录,这些数字表示系统当前运行的进程号;

其中/proc/N/fd目录下面保存了打开的文件描述符,指向实际文件的一个链接。如下:

复制代码代码如下:

[root@XXXXXXX_10_1_17_138 song_test]# ll/proc/25465/fd

total 0

lrwx------ 1 root root 64 Apr 14 09:36 0->/dev/pts/4(deleted)

lrwx------ 1 root root 64 Apr 14 09:36 1->/dev/pts/4(deleted)

lrwx------ 1 root root 64 Apr 14 09:36 10-> socket:[2289128790]

lrwx------ 1 root root 64 Apr 14 09:36 100-> socket:[2305227922]

lrwx------ 1 root root 64 Apr 14 09:36 101-> socket:[2305224138]

lrwx------ 1 root root 64 Apr 14 09:36 102-> socket:[2305233625]

lrwx------ 1 root root 64 Apr 14 09:36 103-> socket:[2305215571]

lrwx------ 1 root root 64 Apr 14 09:36 104-> socket:[2305243589]

lrwx------ 1 root root 64 Apr 14 09:36 105-> socket:[2305394065]

lrwx------ 1 root root 64 Apr 14 09:36 106-> socket:[2305394002]

我们想查看101 Socket文件描述符的链接状态该怎么看呢?聪明的注意到后面有个数字【2305224138】,这个数字又是哪儿来的呢?看客请往下看。

在/proc/net/tcp目录下面保存了所有TCP链接的状态信息。

复制代码代码如下:

[root@XXXXXXX_10_1_17_138 song_test]# cat/proc/net/tcp

sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode

0: 8A11010A:7DC8 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 764789417 1 ffff881051dfcb40 99 0 0 10-1

1: 8A11010A:0369 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 737748331 1 ffff88106af8f7c0 99 0 0 10-1

51: 8A11010A:FAF4 9C01010A:0CEA 06 00000000:00000000 03:00000938 00000000 0 0 0 2 ffff8810516c01c0

52: 8A11010A:21CD 0964010A:2227 01 00000000:00000000 00:00000000 00000000 0 0 2305224138 2 ffff8801402f55c0 23 3 30 10-1

53: 8A11010A:FB8A 9C01010A:0CEA 06 00000000:00000000 03:000012A8 00000000 0 0 0 2 ffff8810516c04c0

54: 8A11010A:73E5 4511010A:0050 06 00000000:00000000 03:00000EA8 00000000 0 0 0 2 ffff88106898a880

55: 8A11010A:89AD F300010A:1F90 08 00000000:00000001 00:00000000 00000000 0 0 2305271480 1 ffff880869b59740 23 3 0 10-1

187: 8A11010A:0ACB 8811010A:1F90 06 00000000:00000000 03:0000028E 00000000 0 0 0 2 ffff881050e9ccc0

188: 8A11010A:FB6C 9C01010A:0CEA 06 00000000:00000000 03:000010CB 00000000 0 0 0 2 ffff88104fd8dd80

看上数字【2305224138】没有,就是这儿来的,到此我们可以找出链接的IP、PORT链接四元组【8A11010A:21CD 0964010A:2227】这个地方是用十六进制保存的,换算成十进制方式【10.1.17.138:8653 10.1.100.9:8743】;

去网络连接状态里面看一下:

复制代码代码如下:

[root@XXXXXXX_10_1_17_138 song_test]# netstat-ntp

Active Internet connections(w/o servers)

Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name

tcp 0 0 10.1.17.138:64428 10.1.1.156:3306 TIME_WAIT-

tcp 0 0 10.1.17.138:64244 10.1.1.156:3306 TIME_WAIT-

tcp 0 166 10.1.17.138:8653 10.1.100.9:8743 ESTABLISHED 25465/./index_searc

tcp 0 0 10.1.17.138:64394 10.1.1.156:3306 TIME_WAIT-

tcp 0 0 10.1.17.138:29669 10.1.17.69:80 TIME_WAIT-

tcp 0 0 10.1.17.138:46336 10.1.17.68:80 TIME_WAIT-

tcp 0 0::ffff:10.1.17.138:8080::ffff:10.1.17.136:27247 TIME_WAIT-

回到开始的问题:101 Socket文件描述符代表的是本地【10.1.17.138:8653】到【10.1.100.9:8743】的一条TCP连接!

阅读剩余
THE END