Linux之网络套接字

首先我们在网络基础1的基础上就要先初步认识一下UDP和TCP协议

认识TCP协议

此处我们先对TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识;

后面我们再详细讨论TCP的一 些细节问题.

传输层协议

有连接

可靠传输

面向字节流

认识UDP协议
此处我们也是对UDP(User Datagram Protocol 用户数据报协议)有一个直观的认识;

后面再详细讨论

传输层协议
无连接.
不可靠传输
面向数据报

两者并没有绝对的好坏之分。

通知像对可靠性要求非常高的就选tcp(银行等不允许信息丢失的),较低的就选udp(比如网络直播这种可以允许少量信息丢失的)。

然后这个地方我们要补充一些知识!

我们以前已经学过了大小端的区别!

磁盘文件中的多字节数据相对于文件中的偏

移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?


发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;
接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;因此,网络数据流的地址应这样规定:

先发出的数据是低地址,后发出的数据是高地址.
TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.
不管这台主机是大端机还是小端机,都会按照这个TCP/IP规定的网络字节序来发送/接收数据,如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略,直接发送即可;

所以我们就有默认的接口来进行大小端转换!

上面是常见的tcp协议用的API,我们之后会细细讲!

然后我们可以看到上面的参数中都有一个结构体sockaddr,这是什么东西呢?我们也介绍一下!

我们现在讲的就是网络套接字!

用的就是sockaddr_in这个结构体,sockaddr_un则是域间套接字

但是我们平时传的一般都是sockaddr类型,但是在bind函数中会判断sockaddr的类型然后进行强转,然后实现不同种类的通信(类似于多态)。方便使用!!!

接下来我们就可以来看一下具体是如何使用的了!!!

1.创建套接字

首先就是我们必须先创建好套接字,使用socket

其中第一个参数domain表示的是创建的套接字的域,比如是本地通信还是ipv4,ipv6等等(用宏代替)

第二个参数则是类型,比如是面向字节流,还是面向数据报的!

第三个参数则是协议类型的,但是由于前面两个参数已经让整个使用非常清晰了,一般填0就可以了。

返回值则是fd(文件描述符)。所以其实socket的本质也是在底层打开一个文件(网卡文件),这就体现了Linux一切皆文件!!!

2.绑定

当我们创建好套接字以后,我们需要将特定的网络地址(ip或端口号)与我们的套接字进行绑定,然后套接字就会开始监听对应地址的数据!

第一个参数就是sockfd也就是刚才的的网络文件描述符!

第二个参数就是我们在网络基础1讲的sockaddr结构,这个地方对应的是通用的那种结构,我们之后要将我们的sockaddr_in结构(ipv4网络)强转成sockaddr传入进行使用。

第三个就是我们sockaddr结构体的长度。

那么在绑定之前我们先要将我们的sockaddr结构体进行设置才行!

第一步我们先要清空我们的local(sckaddr_in的结构体),然后再设置,可以防止一些意外情况的发生,是一个习惯性动作。

然后就要设置3个主要的参数

1:sin_family(协议家族),例如AF_INET就是使用ipv4协议家族!

2.sin_port就是本台主机的端口号,但是由于要在网络传输,所以我们必须把他转换成网络字节序列(小端),这个地方就可以用htons进行转换!

3:s_addr是sin_addr里面的成员,但是也是唯一的成员,所以我们一般就是直接连续使用就可以了,不需要纠结!然后我们的s_addr是一个32位的网络字节序的整数,而我们通常的ip都是字符串类型,所以需要用inet_addr进行转换才能匹配!

在我们设置好结构体以后我们就可以正式绑定了!传入我们的sockfd和结构体以及相应的长度即可完成绑定!

至此我们udp的前期准备就已经完成了!!!非常简单!

然后我们就要开始学习如何接发消息了!

所以我们先来学习一下接收的接口!

第一个参数仍然是套接字。

第二个参数是缓冲区的位置。

第三个参数是缓冲区的大小。

第四个参数是接受的方式(一般写0即阻塞式接受)

第五个参数就是收到的sockaddr结构体

第六个就是结构体的长度大小

下面就是一个使用的实例!

然后就是发送的实例

前四个参数和上面一致,不再赘述!

后面两个参数类型其实和前面一致的,但是我们该填什么呢?

这就是为什么我们要先接受的原因,往往都是我们客户端向服务器率先发起请求,也就是在这个过程中我们已经把我们的信息发送过去,于是服务器就可以把接受到的数据填入,然后进行发回信息实现通信!!!

于是我们就基本学完了udp的相关接口了!!!

接下来我们就开始学习TCP了!!!

前面的socket和bind与udp是一样的,只需要更改一些宏就可以了。

socket处就要改成面向字节流的,也即SOCK_STREAM。

但是tcp相比udp多的东西就是监听!

这个接口非常简单,只用传入sockfd和backlog就行。

backlog是全连接队列的长度,我们之后再细讲,这个地方只要设置成10就可以了。(只要不是很大就行,)

然后就是accept,与新链接建立通信!

这三个参数相信大家已经很熟悉了,就不再赘述。

我们着重看一下返回值,其实也是一个文件描述符!

而这个文件描述符和socket的文件描述符的区别就是后者的只负责接收底层的链接,至于具体的网络通信文件描述符则是accept返回的fd.

同理客户端也要用connet发起链接。

这样双方一旦建立起链接,后面就可以通过write和read在同一fd指向的文件下进行读写数据交互,也即完成了网络通信!!!并且这个链路是全双工的,双方可以同时分别进行读写不会干扰(因为內部实现了两个缓冲区)!!!

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值