网络协议 11 - Socket 编程(下)
之前我们基本了解了网络通信里的大部分协议,一直都是在“听”的过程。很多人都会觉得,好像看懂了,但关了页面回忆起来,好像又什么都没懂。这次咱们就“真枪实弹”的码起来,再用一个“神器”-网络分析系统详细跟踪下数据包的生命历程,让我们的理论真实的呈现出来,对网络通信感兴趣的博友,还可以自己拿着系统分析一遍,你一定会大有所获。
不多说,直接上代码。有兴趣的博友可以按各编程语言进行相关改写,然后拿着我们的分析系统真实的看看网络通信过程。
本机请求转发到网关
代码中的 192.168.1.10 是内网另一台服务器,楼主的 IP 是 192.168.1.73。在本机跑服务器的时候,要做一个路由配置,否则分析系统无法抓取相关的包。window 下可按下面步骤配置:
- 管理员身份打开 DOS 窗口;
- route add 本机ip mask 255.255.255.255 网关ip(路由转发,还记得吗?忘记了?点我点我点我);
什么?不知道怎么查 IP 和网关?点我告诉你
操作完成后记得删除转发规则,否则,你会发现本机的请求,速度会变得很慢、、、
实例:
// 添加路由转发规则
route add 192.168.1.73 mask 255.255.255.255 192.168.1.1
// 删除转发规则
route delete 192.168.1.73
基于 TCP 的 Socket
服务端:
<?php
/**
* 1. socket_create: 新建 socket
* 2. socket_bind: 绑定 IP 和 port
* 3. socket_listen: 监听
* 4. socket_accept: 接收客户端连接,返回连接 socket
* 5. socket_read: 读取客户端发送数据
* 6. socket_write: 返回数据
* 7. socket_close: 关闭 socket
*/
$ip = '192.168.1.10';
$port = 23333;
// $port = 80;
$sk = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
!$sk && outInfo('socket_create error');
// 绑定 IP
!socket_bind($sk, $ip, $port) && outInfo('socket_bind error');
// 监听
!socket_listen($sk) && outInfo('sever listen error');
outInfo("Success Listen: $ip:$port", 'INFO');
while (true) {
$accept_res = socket_accept($sk);
!$accept_res && outInfo('sever accept error');
$reqStr = socket_read($accept_res, 1024);
if (!$reqStr) outInfo('sever read error');
outInfo("Server receive client msg: $reqStr", 'INFO');
$response = 'Hello A, I am B. you msg is : ' . $reqStr . PHP_EOL;
if (socket_write($accept_res, $response, strlen($response)) === false) {
outInfo('response error');
}
socket_close($accept_res);
}
socket_close($sk);
function outInfo($errMsg, $level = 'ERROR')
{
if ($level === 'ERROR') {
$errMsg = "$errMsg, msg: " . socket_strerror(socket_last_error());
}
echo $errMsg . PHP_EOL;
$level === 'ERROR' && die;
}
客户端:
<?php
/**
* 1. socket_create: 新建 socket
* 2. socket_connect: 连接服务端
* 3. socket_write: 给服务端发数据
* 4. socket_read: 读取服务端返回的数据
* 5. socket_close: 关闭 socket
*/
$ip = '192.168.1.10';
$port = 23333;
$sk = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
!$sk && outInfo('socket_create error');
!socket_connect($sk, $ip, $port) && outInfo('connect fail');
$msg = 'hello, I am A';
if (socket_write($sk, $msg, strlen($msg)) === false) {
outInfo('socket_write fail');
}
while ($res = socket_read($sk, 1024)) {
echo 'server return message is:'. PHP_EOL. $res;
}
socket_close($sk);//工作完毕,关闭套接流
function outInfo($errMsg, $level = 'ERROR')
{
if ($level === 'ERROR') {
$errMsg = "$errMsg, msg: " . socket_strerror(socket_last_error());
}
echo $errMsg . PHP_EOL;
$level === 'ERROR' && die;
}
上面的代码是基于 PHP 原生 Socket 写的,其它语言也有对应 Socket 操作函数,进行相关的改写即可。主要是下面的分析过程。

如上图,这是我们的分析系统捕捉的所有数据传输过程,你可以真实的看到每一步都发生了什么,以及对应的状态的改变(图片较大,建议右键在新标签页打开看)。
在图中上半部分,我们可以看到分析系统将整个 TCP 的生命历程分为了三个阶段:建立连接、交易、关闭连接。这和我们之前了解的理论知识完全相符。
左下角的交易时序图,则详细记录了客户端和服务端每次通信的详细信息,而右下角部分,则展示了每次通信,数据包的状态等信息。
基于 UDP 的Socket
<?php
/**
* 1. socket_create: 新建 socket
* 2. socket_bind: 绑定 IP 和 port
* 3. socket_recvfrom: 读取客户端发送数据
* 4. socket_sendto: 返回数据
* 5. socket_close: 关闭 socket
*/
$ip = '192.168.1.10';
$port = 23333;
$sk = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
!$sk && outInfo('socket_create error');
// 绑定 IP
!socket_bind($sk, $ip, $port) && outInfo('socket_bind error');
outInfo("Success Listen: $ip:$port", 'INFO');
while (true) {
$from = '';
$reqPort = 0;
if (!socket_recvfrom($sk, $buf, 1024, 0, $from, $reqPort)) {
outInfo('sever socket_recvfrom error');
}
outInfo("Received msg $buf from remote address $from:$port", 'INFO');
$response = "Hello $from:$port, I am Server. your msg : " . $buf . PHP_EOL;
if (!socket_sendto($sk, $response, strlen($response), 0, $from, $reqPort)) {
outInfo('socket_sendto error');
}
}
socket_close($sk);
function outInfo($errMsg, $level = 'ERROR')
{
if ($level === 'ERROR') {
$errMsg = "$errMsg, msg: " . socket_strerror(socket_last_error());
}
echo $errMsg . PHP_EOL;
$level === 'ERROR' && die;
}
客户端:
<?php
/**
* 1. socket_create: 新建 socket
* 2. socket_write: 给服务端发数据
* 3. socket_read: 读取服务端返回的数据
* 4. socket_close: 关闭 socket
*/
$ip = '192.168.1.10';
$port = 23333;
$sk = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
!$sk && outInfo('socket_create error');
$msg = 'hello, I am A';
if (!socket_sendto($sk, $msg, strlen($msg), 0, $ip, $port)) {
outInfo('socket_sendto fail');
}
$from = '';
$reqPort = 0;
if (!socket_recvfrom($sk, $buf, 1024, 0, $from, $reqPort)) {
outInfo('server socket_recvfrom error');
}
outInfo("Received $buf from server address $from:$port", 'INFO');
socket_close($sk);
function outInfo($errMsg, $level = 'ERROR')
{
if ($level === 'ERROR') {
$errMsg = "$errMsg, msg: " . socket_strerror(socket_last_error());
}
echo $errMsg . PHP_EOL;
$level === 'ERROR' && die;
}
UDP 数据包分析图:

如上图,UDP 数据包分析图,明显比 TCP 要简单很多,人家单纯嘛,就不多说了。不过要注意的,写代码的时候,UDP 的服务端,在循环里千万不要关闭 Socket。
分析系统介绍
上面用到的分析系统叫:科来网络分析系统,点我下载。这个分析系统很良心,提供了一个免费的技术交流版。有兴趣的小伙伴可以下载下来玩玩,很强大。
欢迎添加个人微信号:Like若所思。
欢迎关注我的公众号,不仅为你推荐最新的博文,还有更多惊喜和资源在等着你!一起学习共同进步!

网络协议 11 - Socket 编程(下)的更多相关文章
- 网络协议 11 - Socket 编程(下):眼见为实耳听为虚
系列文章传送门: 网络协议 1 - 概述 网络协议 2 - IP 是怎么来,又是怎么没的? 网络协议 3 - 从物理层到 MAC 层 网络协议 4 - 交换机与 VLAN:办公室太复杂,我要回学校 网 ...
- 网络协议 10 - Socket 编程(上):实践是检验真理的唯一标准
系列文章传送门: 网络协议 1 - 概述 网络协议 2 - IP 是怎么来,又是怎么没的? 网络协议 3 - 从物理层到 MAC 层 网络协议 4 - 交换机与 VLAN:办公室太复杂,我要回学校 网 ...
- 网络协议 10 - Socket 编程(上)
前面一直在说各种协议,偏理论方面的知识,这次咱们就来认识下基于 TCP 和 UDP 协议这些理论知识的 Socket 编程. 说 TCP 和 UDP 的时候,我们是分成客户端和服务端来认识的, ...
- 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
- 网络编程基础:网络基础之网络协议、socket模块
操作系统(简称OS)基础: 应用软件不能直接操作硬件,能直接操作硬件的只有操作系统:所以,应用软件可以通过操作系统来间接操作硬件 网络基础之网络协议: 网络通讯原理: 连接两台计算机之间的Intern ...
- 基于TCP协议的socket编程
什么是socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...
- linux网络编程之socket编程(一)
今天开始,继续来学习linux编程,这次主要是研究下linux下的网络编程,而网络编程中最基本的需从socket编程开始,下面正式开始学习: 什么是socket: 在学习套接口之前,先要回顾一下Tcp ...
- 网络协议之:socket协议详解之Socket和Stream Socket
目录 简介 Socket是什么 Stream Socket 使用socat创建一个TCP服务器 使用ss检查TCP连接 使用nc连接socket 总结 简介 不管是在普通的网络编程中还是在netty中 ...
- 关于网络协议和socket编程基本概念
TCP协议可以说已经是IT人耳熟能详的协议,最近在学习socket网络编程时后重新温习一下这个协议,针对一些问题做了一些总结,很多理解可能还不是很准确. 1. 协议是什么?所谓的各种网络协议无非是一种 ...
随机推荐
- kubeadm安装kubernetes 1.16.2
目录 简介 环境说明 安装 准备基础环境 安装docker 安装kubeadm.kubelet.kubectl 配置kubeadm-config.yaml 部署master 安装flannel网络插件 ...
- linux centos7下源码 tar安装mysql5.7.22或mysql5.7.20 图文详解
之前用的rpm安装的每次安装都是最新的,,,导致每次版本不统一... 现在用tar包安装5.7.22和5.7.20一样的 5.7.20之后的和之前的版本还是有点不一样的 官网地址 https:// ...
- Android Studio Analyze APK 一直显示 Parsing Manifest探因及解决
一.背景 大家都知道,Android Studio开发工具自带了Analyze Apk,可以很方便的分析Apk文件.具体位于菜单build >> Analyze APK...路径下,点击后 ...
- 想让自己的项目6666,可是 Chrome 不答应!
读万卷书,行万里路!有的技能可以从书里学会,有的技能却需要在实战中打怪升级慢慢掌握,今天就来和大家聊一个很多小伙伴经常遇到的问题. 缘起 有人向松哥反映,在搭建微服务分布式配置中心 Spring Cl ...
- Centos 7搭建Gitlab服务器超详细Centos 7搭建Gitlab服务器超详细(搭建成功)
一. 安装并配置必要的依赖关系在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget,以下这些命令也会打开系统防火墙中的HTTP和SSH端口访问. 注意:用户不 ...
- Redis(六)Lua脚本的支持
Redis为什么需要Lua脚本的支持 当应用需要Redis完成一些Redis命令不支持的特性时,要么扩展Redis client或者更甚至编写c扩展Redis server.这都大大造成了应用的实现的 ...
- 【linux】查看某个进程PID对应的文件句柄数量,查看某个进程当前使用的文件句柄数量
================================ 1.linux所有句柄查询 lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more ...
- .net H5微信,支付宝充值
using clientpay.Data.AlipayConfig; using clientpay.Data.BLL; using clientpay.Data.Entity; using Aop. ...
- python 进程和线程-简介及进程
进程和线程的关系及应用 参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017627212385376 多任务: 什么叫“多任务”呢?简 ...
- Python文件属性模块Os.path
Python文件属性模块Os.path介绍 os.path模块主要用于文件属性获取和判断,在编程中会经常用到,需要熟练掌握.以下是该模块的几种常用方法. os.path官方文档:http://docs ...