之前我们基本了解了网络通信里的大部分协议,一直都是在“听”的过程。很多人都会觉得,好像看懂了,但关了页面回忆起来,好像又什么都没懂。这次咱们就“真枪实弹”的码起来,再用一个“神器”-网络分析系统详细跟踪下数据包的生命历程,让我们的理论真实的呈现出来,对网络通信感兴趣的博友,还可以自己拿着系统分析一遍,你一定会大有所获。

    不多说,直接上代码。有兴趣的博友可以按各编程语言进行相关改写,然后拿着我们的分析系统真实的看看网络通信过程。

本机请求转发到网关

    代码中的 192.168.1.10 是内网另一台服务器,楼主的 IP 是 192.168.1.73。在本机跑服务器的时候,要做一个路由配置,否则分析系统无法抓取相关的包。window 下可按下面步骤配置:

  1. 管理员身份打开 DOS 窗口;
  2. 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 编程(下)的更多相关文章

  1. 网络协议 11 - Socket 编程(下):眼见为实耳听为虚

    系列文章传送门: 网络协议 1 - 概述 网络协议 2 - IP 是怎么来,又是怎么没的? 网络协议 3 - 从物理层到 MAC 层 网络协议 4 - 交换机与 VLAN:办公室太复杂,我要回学校 网 ...

  2. 网络协议 10 - Socket 编程(上):实践是检验真理的唯一标准

    系列文章传送门: 网络协议 1 - 概述 网络协议 2 - IP 是怎么来,又是怎么没的? 网络协议 3 - 从物理层到 MAC 层 网络协议 4 - 交换机与 VLAN:办公室太复杂,我要回学校 网 ...

  3. 网络协议 10 - Socket 编程(上)

    前面一直在说各种协议,偏理论方面的知识,这次咱们就来认识下基于 TCP 和 UDP 协议这些理论知识的 Socket 编程.     说 TCP 和 UDP 的时候,我们是分成客户端和服务端来认识的, ...

  4. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  5. 网络编程基础:网络基础之网络协议、socket模块

    操作系统(简称OS)基础: 应用软件不能直接操作硬件,能直接操作硬件的只有操作系统:所以,应用软件可以通过操作系统来间接操作硬件 网络基础之网络协议: 网络通讯原理: 连接两台计算机之间的Intern ...

  6. 基于TCP协议的socket编程

    什么是socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...

  7. linux网络编程之socket编程(一)

    今天开始,继续来学习linux编程,这次主要是研究下linux下的网络编程,而网络编程中最基本的需从socket编程开始,下面正式开始学习: 什么是socket: 在学习套接口之前,先要回顾一下Tcp ...

  8. 网络协议之:socket协议详解之Socket和Stream Socket

    目录 简介 Socket是什么 Stream Socket 使用socat创建一个TCP服务器 使用ss检查TCP连接 使用nc连接socket 总结 简介 不管是在普通的网络编程中还是在netty中 ...

  9. 关于网络协议和socket编程基本概念

    TCP协议可以说已经是IT人耳熟能详的协议,最近在学习socket网络编程时后重新温习一下这个协议,针对一些问题做了一些总结,很多理解可能还不是很准确. 1. 协议是什么?所谓的各种网络协议无非是一种 ...

随机推荐

  1. 宽字符与Unicode (c语言 汉语字符串长度)

    在C语言中,我们使用char来定义字符,占用一个字节,最多只能表示128个字符,也就是ASCII码中的字符.计算机起源于美国,char 可以表示所有的英文字符,在以英语为母语的国家完全没有问题. 但是 ...

  2. golang学习笔记 --flag

    概述 flag包提供了一系列解析命令行参数的功能接口 命令行语法 命令行语法主要有以下几种形式 -flag //只支持bool类型 -flag=x -flag x //只支持非bool类型 以上语法对 ...

  3. Prometheus监控学习笔记之Prometheus 2.x版本的常用变化

    最近用了prometheus 2.0 版本,感觉改变还是有点大,现将改变相关记录如下: 1.prometheus.yml文件配置修改后,要想重新加载,必须在启动的时候添加参数: --web.enabl ...

  4. Python学习笔记之try-except

    Python使用被称为异常的特殊对象来管理程序执行期间发生的错误.每当发生让Python不知所措的错误时,它都会创建一个异常对象.如果你编写了处理该异常的代码,程序将继续运行:如果你未对异常进行处理, ...

  5. 详解:Java字符串类型"switch"的底层原理

    前言: 最近更新得会比较频繁,希望大家见谅哦! 也感谢关注我的人,我会更加更加努力去做的! 基础 我们现在使用的Java的版本,基本上是都支持String类型的.当然除了String类型,还有int. ...

  6. PHP上传图片基本代码示例

    一.HTML代码如下: <form name="form2" method="post" action="?type=add" enc ...

  7. 【转载】Gradle学习 第八章:依赖管理基础

    转载地址:http://ask.android-studio.org/?/article/10 This chapter introduces some of the basics of depend ...

  8. WorkFlow三:CLASS事件触发工作流

    1.创建关键字段结构.这里没有新建,使用前面创建的结构: 2.SE24创建类:保存激活. 3.接口里添加IF_WORKFLOW并激活.(其他两个激活就出现了,不用管) 4.在属性页签中定义两个属性,其 ...

  9. 【学习笔记】大数据技术原理与应用(MOOC视频、厦门大学林子雨)

    1 大数据概述 大数据特性:4v volume velocity variety value 即大量化.快速化.多样化.价值密度低 数据量大:大数据摩尔定律 快速化:从数据的生成到消耗,时间窗口小,可 ...

  10. sqlserver清空删除日志

    USE [lzdxdb] GO ALTER DATABASE lzdxdb SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE lzdxdb SET ...