自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

動手學(xué)習(xí)TCP系列之服務(wù)端狀態(tài)變遷

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
上一篇文章介紹了TCP狀態(tài)機,并且通過實驗了解了TCP客戶端正常的狀態(tài)變遷過程。那么,本篇文章就一起看看TCP服務(wù)端的正常狀態(tài)變遷過程。

上一篇文章介紹了TCP狀態(tài)機,并且通過實驗了解了TCP客戶端正常的狀態(tài)變遷過程。

那么,本篇文章就一起看看TCP服務(wù)端的正常狀態(tài)變遷過程。

服務(wù)端狀態(tài)變遷

根據(jù)上一篇文章中的TCP狀態(tài)變遷圖,可以得到服務(wù)器的正常狀態(tài)變遷流程如下:

CLOSED -> LISTEN -> SYN_RECV -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED

服務(wù)端狀態(tài)變遷實驗

下面就結(jié)合上面分析出來的服務(wù)端狀態(tài)變遷表,利用Pcap.Net來模擬服務(wù)端正常的狀態(tài)變遷過程。

代碼實現(xiàn)

跟前面幾次正好相反,這次我們將在宿主機運行Pcap.Net實現(xiàn)的服務(wù)端,然后在虛擬機運行一個客戶端。

對于服務(wù)端,主程序中設(shè)置了源和目的端的連接信息,這次宿主機中的服務(wù)端將監(jiān)聽“3333”端口。

然后,程序中設(shè)置了服務(wù)端TCP初始狀態(tài)為"LISTENING",然后就直接運行監(jiān)聽函數(shù)了。

// Open the output device
using (PacketCommunicator communicator = selectedDevice.Open(System.Int32.MaxValue, // name of the device
PacketDeviceOpenAttributes.Promiscuous, // promiscuous mode
1)) // read timeout
{
EndPointInfo endPointInfo = new EndPointInfo();
endPointInfo.SourceMac = "08:00:27:00:C0:D5";
endPointInfo.DestinationMac = "";
endPointInfo.SourceIp = "192.168.56.101";
endPointInfo.DestinationIp = "";
endPointInfo.SourcePort = 3333;
endPointInfo.DestinationPort = 0;
using (BerkeleyPacketFilter filter = communicator.CreateFilter("tcp port " + endPointInfo.SourcePort))
{
// Set the filter
communicator.SetFilter(filter);
}
tcpStatus = TCPStatus.LISTENING;
PacketHandler(communicator, endPointInf)
}
這次的監(jiān)聽函數(shù)"PacketHandler"中的邏輯,跟上一次客戶端的例子還是有很大差別的。

首先是期待接收和實際發(fā)送的TCP包類型有很大的差別,其次就是狀態(tài)之間的變遷是完全不同的。但是,代碼的邏輯依然是根據(jù)上面的服務(wù)端狀態(tài)變遷表。

private static void PacketHandler(PacketCommunicator communicator, EndPointInfo endPointInfo)
{
Packet packet = null;
bool running = true;
do{
PacketCommunicatorReceiveResult result = communicator.ReceivePacket(out packet);
switch (result)
{
case PacketCommunicatorReceiveResult.Timeout:
// Timeout elapsed
continue;
case PacketCommunicatorReceiveResult.Ok:
bool isRecvedPacket = (packet.Ethernet.IpV4.Destination.ToString() == endPointInfo.SourceIp) ? true : false;
if (isRecvedPacket)
{
switch (packet.Ethernet.IpV4.Tcp.ControlBits){
case TcpControlBits.Synchronize:
if (tcpStatus == TCPStatus.LISTENING)
{
endPointInfo.DestinationMac = packet.Ethernet.Source.ToString();
endPointInfo.DestinationIp = packet.Ethernet.IpV4.Source.ToString();
endPointInfo.DestinationPort = packet.Ethernet.IpV4.Tcp.SourcePort;
Utils.PacketInfoPrinter(packet);
Packet synAck = Utils.BuildTcpResponsePacket(packet, TcpControlBits.Synchronize | TcpControlBits.Acknowledgment);
communicator.SendPacket(synAck);
tcpStatus = TCPStatus.SYN_RECEIVED;
}break;
case TcpControlBits.Acknowledgment:
if (tcpStatus == TCPStatus.SYN_RECEIVED)
{
tcpStatus = TCPStatus.ESTABLISHED;
Utils.PacketInfoPrinter(packet, tcpStatus);
}
else if (tcpStatus == TCPStatus.LAST_ACK)
{
tcpStatus = TCPStatus.CLOSED;
Utils.PacketInfoPrinter(packet, tcpStatus);
tcpStatus = TCPStatus.LISTENING;
}
else if (tcpStatus == TCPStatus.FIN_WAIT_1)
{
tcpStatus = TCPStatus.FIN_WAIT_2;
Utils.PacketInfoPrinter(packet);
}
break;
case (TcpControlBits.Fin | TcpControlBits.Acknowledgment):
if (tcpStatus == TCPStatus.FIN_WAIT_2)
{
Utils.PacketInfoPrinter(packet);
Packet ack = Utils.BuildTcpResponsePacket(packet, TcpControlBits.Acknowledgment);
communicator.SendPacket(ack);
tcpStatus = TCPStatus.TIME_WAIT;
}
else if (tcpStatus == TCPStatus.ESTABLISHED){
Utils.PacketInfoPrinter(packet);
Packet ack = Utils.BuildTcpResponsePacket(packet, TcpControlBits.Acknowledgment);
communicator.SendPacket(ack);
tcpStatus = TCPStatus.CLOSE_WAIT;
}
break;
default:
Utils.PacketInfoPrinter(packet);
break;
}
}
else
{
switch (packet.Ethernet.IpV4.Tcp.ControlBits)
{
case (TcpControlBits.Synchronize | TcpControlBits.Acknowledgment):
if (tcpStatus == TCPStatus.SYN_RECEIVED)
{
Utils.PacketInfoPrinter(packet, tcpStatus);
}
#p#
break;
case (TcpControlBits.Fin | TcpControlBits.Acknowledgment):
if (tcpStatus == TCPStatus.FIN_WAIT_1)
{
Utils.PacketInfoPrinter(packet, tcpStatus);
}
else if (tcpStatus == TCPStatus.LAST_ACK)
{
Utils.PacketInfoPrinter(packet, tcpStatus);
}
break;
case TcpControlBits.Acknowledgment:
if (tcpStatus == TCPStatus.TIME_WAIT)
{
Utils.PacketInfoPrinter(packet, tcpStatus);
}else if (tcpStatus == TCPStatus.CLOSE_WAIT)
{
Utils.PacketInfoPrinter(packet, tcpStatus);
Packet fin = Utils.BuildTcpPacket(endPointInfo, TcpControlBits.Fin | TcpControlBits.Acknowledgment);
communicator.SendPacket(fin);
tcpStatus = TCPStatus.LAST_ACK;
}break;
default:
Utils.PacketInfoPrinter(packet);
break;
}
}
break;
default:
throw new InvalidOperationException("The result " + result + " should never be reached here");
}
} while (running);
}

對于客戶端,通過Python實現(xiàn)了一個簡單的Socket程序來模擬客戶端行為:

 

from socket import *
import time
HOST = "192.168.56.101"
PORT = 3333
BUFSIZ = 1024
ADDR = (HOST, PORT)
client = socket(AF_INET, SOCK_STREAM)
client.connect(ADDR)
time.sleep(5)
client.close()

 

運行效果

這次,宿主機上運行的是服務(wù)端,虛擬機運行的是客戶端,打開Wireshark監(jiān)聽"VirtualBox Host-Only Network"網(wǎng)卡,并設(shè)置filter為"port 3333"。

運行服務(wù)端程序,服務(wù)端將處于監(jiān)聽狀態(tài)。這是在虛擬機中運行"client.py"。這時,通過服務(wù)端console可以看到客戶端和服務(wù)端之間的包,以及服務(wù)端的狀態(tài)變遷。

 

Wireshark依然顯示的是TCP連接建立和終止的過程。

 

netstat命令

netstat是控制臺命令,是一個監(jiān)控TCP/IP網(wǎng)絡(luò)的非常有用的工具,它可以顯示路由表、實際的網(wǎng)絡(luò)連接以及每一個網(wǎng)絡(luò)接口設(shè)備的狀態(tài)信息。netstat用于顯示與IP、TCP、UDP和ICMP協(xié)議相關(guān)的統(tǒng)計數(shù)據(jù),一般用于檢驗本機各端口的網(wǎng)絡(luò)連接情況。

實驗中的宿主機系統(tǒng)是Win7,下面看看通過 netatat /? 獲得的幫助信息:

 

netstat命令失效?

雖然說上面的程序可以打印出服務(wù)端的狀態(tài)變遷過程,但是這次讓我們通過netstat命令查看一下。

為了方便查看,將"client.py"中的"time.sleep(5)"改為"time.sleep(300)",使客戶端跟服務(wù)器之間的連接保持300秒??蛻舳说亩丝谔枮?quot;1090"。

 

這時,分別在服務(wù)端和客戶端cmd窗口中執(zhí)行 netstat -anp TCP | findstr "192.168.56" 命令,查看包含"192.168.56"字符串的TCP連接:

服務(wù)端:

 

客戶端:

 

為什么服務(wù)端看不到TCP連接?就像我們***篇介紹的那樣,Pcap.Net是不經(jīng)過操作系統(tǒng)協(xié)議棧的,所以這也就解釋了為什么"netstat"命令發(fā)現(xiàn)不了服務(wù)端的TCP連接。

等300秒結(jié)束后,客戶端會發(fā)送終止連接請求。當(dāng)連接終止后,可以看大客戶端的TCP連接狀態(tài)變成了"TIME_WAIT"。

客戶端:

 

總結(jié)

本文中根據(jù)TCP狀態(tài)變遷圖,得到了服務(wù)端的狀態(tài)變遷表。

然后使用Pcap.Net,基于服務(wù)端的狀態(tài)變遷表,構(gòu)建了一個簡單的服務(wù)端,展示了服務(wù)端狀態(tài)變遷的過程。

文中還簡單的介紹了"netstat"命令,通過這個命令可以查看TCP連接的狀態(tài),結(jié)合這個命令,可以更好的了解TCP狀態(tài)。

責(zé)任編輯:何妍 來源: 博客園
相關(guān)推薦

2015-10-10 09:51:51

TCP網(wǎng)絡(luò)協(xié)議客戶端

2015-10-13 15:09:31

2015-10-08 14:03:01

TCP網(wǎng)絡(luò)協(xié)議

2015-10-09 13:15:03

TCP網(wǎng)絡(luò)協(xié)議

2015-10-14 09:44:55

TCP網(wǎng)絡(luò)協(xié)議數(shù)據(jù)傳輸

2015-10-15 09:38:48

TCP網(wǎng)絡(luò)協(xié)議定時器

2022-05-08 17:53:38

Nacos服務(wù)端客戶端

2023-08-14 08:17:13

Kafka服務(wù)端

2016-03-18 09:04:42

swift服務(wù)端

2014-09-19 09:46:46

TCPIP

2022-09-05 14:36:26

服務(wù)端TCP連接

2013-03-25 10:08:44

PHPWeb

2012-03-02 10:38:33

MySQL

2022-05-22 13:55:30

Go 語言

2021-06-30 06:59:47

Zabbix Server服務(wù)端MySQL

2010-08-03 09:59:30

NFS服務(wù)

2016-11-03 09:59:38

kotlinjavaspring

2022-08-13 13:05:43

TCP服務(wù)端四次揮手

2021-05-25 08:20:37

編程技能開發(fā)

2020-03-31 20:23:46

C語言TCP服務(wù)器
點贊
收藏

51CTO技術(shù)棧公眾號