linux Socket

基本的UDP Socket编程

UDP通信的流程比较简单,因此要搭建这么一个常用的UDP通信框架也是比较简单的。以下是UDP的框架图。

UDP SOCKET通信

由以上框图可以看出,客户端要发起一次请求,仅仅需要两个步骤(socket和sendto),而服务器端也仅仅需要三个步骤即可接收到来自客户端的消息(socket、bind、recvfrom)。

Send, sendto, 和 sendmsg 用于向另一个套接字传递消息. Send 仅仅用于连接套接字,而 sendtosendmsg 可用于任何情况下.

  • read()/write()
  • recv()/send()
  • readv()/writev()
  • recvmsg()/sendmsg()
  • recvfrom()/sendto()

目标地址用 to 指定, tolen 定义其长度.消息的长度用 len 指定. 如果消息太长不能通过下层协议,函数将返回 EMSGSIZE 错误,消息也不会被送出.

在数据传送过程中所产生的错误不会返回给 send. 如果发生本地错误,则返回-1.

当要发送的消息长度大于套接字当前可用缓冲区时, send 将阻塞,除非在套接字上设置了非阻塞式输入输出模式. 对于非阻塞模式,这种情况下将返回 EAGAIN 错误.

udp的connect函数

UDP网络编程中也有connect函数,但它仅仅用于表示确定了另一方的地址,并没有其他含义。
有了以上认识后,我们可以知道UDP套接字有以下区分:
1)未连接的UDP套接字
2)已连接的UDP套接字

对于未连接的套接字,也就是我们常用的的UDP套接字,我们使用的是sendto/recvfrom进行信息的收发,目标主机的IP和端口是在调用sendto/recvfrom时确定的;

在一个未连接的UDP套接字上给两个数据报调用sendto函数内核将执行以下六个步骤:
1)连接套接字
2)输出第一个数据报
3)断开套接字连接
4)连接套接字
5)输出第二个数据报
6)断开套接字连接

对于已连接的UDP套接字,必须先经过connect来向目标服务器进行指定,然后调用read/write进行信息的收发,目标主机的IP和端口是在connect时确定的,也就是说,一旦connect成功,我们就只能对该主机进行收发信息了。

已连接的UDP套接字给两个数据报调用write函数内核将执行以下三个步骤:
1)连接套接字
2)输出第一个数据报
3)输出第二个数据报

由此可以知道,当应用进程知道给同一个目的地址的端口号发送多个数据报时,显示套接字效率更高。

下面给出带connect函数的UDP通信框架

使用connect函数的UDP通信框架

Socket端口通信运行在会话层,并不是应用层,Socket抓包的原理与应用层Http(s)有着显著的区别。准确的说,Http(s)抓包是真正的“中间人”抓包,而Socket抓包是在接口上进行转储;Http(s)抓包是明显的将一套C/S架构通信分裂成两套完整的通信过程,而Socket抓包是在接口上将发送与接收的内容存储下来,并不干扰其原本的通信过程。

对于安卓应用来说,Socket通信天生又分为两种JavaSocket通信和NativeSocket通信。

  • Java层:使用的是java.net.InetAddressjava.net.Socketjava.net.ServerSocket等类,与证书绑定的情形类似,也可能存在着自定义框架的Socket通信,这时候就需要具体情况具体分析,比如谷歌的protobuf框架等;
  • Native层:一般使用的是C Socket API,一般hooksend()recv()函数可以得到其发送和接受的内容

Java层

Socket通信

Native层

Socket通信

一般使用的是C Socket API,一般hooksend()recv()函数可以得到其发送和接受的内容。udp一般使用的sendto()

posted @ 2020-11-05 22:13  Runope丶  阅读(130)  评论(0编辑  收藏  举报