C# 帧听端口HTTP请求并以TCP方式模拟HTTP
首先我们先看看HTTP GET方式发送和返回的数据格式:
Request:
1 GET /talent_liv/1.liv?cmd=check&chanid=1 HTTP/1.1 2 Accept: */* 3 Accept-Language: zh-cn 4 5 6 User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E) 7 Accept-Encoding: gzip, deflate 8 Host: 192.168.2.51 9 Connection: Keep-Alive
代码中红色片段为GET请求的头,也就是待会我们监听到后需要的信息。
Response:
1 HTTP/1.1 200 OK 2 Connection: close 3 Date: Fri, 07 Mar 2014 06:05:54 GMT 4 Server: Microsoft-IIS/6.0 5 X-Powered-By: ASP.NET 6 Content-Type:text/xml 7 Content-Length:499 8 //两个回车换行后Body 9 <?xml version="1.0" encoding="GB2312" ?><xmlRoot XmlType="Check"><Channel ID = "1" Name = "........" Capture = "2" Record = "0" RecordStartTime = "Unknow" Online = "0"><ENCODER ID = "1" Name = "vga" Type = "ENC_HDEX1000F" Main = "0 kbps" Sub = "0 kbps" Audio = "0 kbps"/><ENCODER ID = "2" Name = "...." Type = "ENC_HDEX1000F" Main = "0 kbps" Sub = "0 kbps" Audio = "0 kbps"/><ENCODER ID = "3" Name = "...." Type = "ENC_HDEX1000F" Main = "0 kbps" Sub = "0 kbps" Audio = "0 kbps"/></Channel></xmlRoot>............
代码中红色片段为模拟HTTPResponse时所需要的必须字段,要注意的是每一行后都要加上回车换行\r\n,Body和Head之间要有两个。
看完HTTP的格式后,我们开始编码:
需要的命名空间:
1 using System.ComponentModel; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Threading; 5 using System.Text.RegularExpressions;
侦听端界面:
XAML代码:
1 <Window x:Class="TCPtoHTTP.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="200" Width="300"> 5 <Grid> 6 <Button Content="开始监听" Height="23" HorizontalAlignment="Left" Margin="97,126,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /> 7 <Button Content="停止监听" Height="23" HorizontalAlignment="Left" Margin="179,126,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" /> 8 <Label Content="IP:" Height="28" HorizontalAlignment="Left" Margin="34,20,0,0" Name="label1" VerticalAlignment="Top" Width="28" /> 9 <TextBox Height="23" HorizontalAlignment="Right" Margin="0,22,24,0" Name="txt_IP" VerticalAlignment="Top" Width="177"/> 10 <Label Content="Port:" Height="28" HorizontalAlignment="Left" Margin="23,65,0,0" Name="label2" VerticalAlignment="Top" Width="39" /> 11 <TextBox Height="23" HorizontalAlignment="Right" Margin="0,69,24,0" Name="txt_Port" VerticalAlignment="Top" Width="177" /> 12 </Grid> 13 </Window>
CS代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 using System.ComponentModel; 15 using System.Net; 16 using System.Net.Sockets; 17 using System.Threading; 18 using System.Text.RegularExpressions; 19 20 21 namespace TCPtoHTTP 22 { 23 /// <summary> 24 /// MainWindow.xaml 的交互逻辑 25 /// </summary> 26 public partial class MainWindow : Window 27 { 28 //后台异步对象 29 BackgroundWorker bgw_TcpPortLisen; 30 //监听线程 31 Thread TCPth; 32 //TCP监听对象 33 TcpListener TCPlis; 34 //IP正则表达式 35 string IpRegex = @"(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\b"; 36 //Port正则表达式 37 string PortRegex = @"^[0-9]*$"; 38 //TCP监听参数 39 string TcpIp = ""; 40 int TcpPort; 41 42 public MainWindow() 43 { 44 InitializeComponent(); 45 bgwInit(); 46 47 } 48 /// <summary> 49 /// 后台异步对象初始化 50 /// </summary> 51 private void bgwInit() 52 { 53 // 54 // bgw_TcpPortLisen 55 // 56 this.bgw_TcpPortLisen = new System.ComponentModel.BackgroundWorker(); 57 this.bgw_TcpPortLisen.WorkerReportsProgress = true; 58 this.bgw_TcpPortLisen.WorkerSupportsCancellation = true; 59 this.bgw_TcpPortLisen.DoWork += new System.ComponentModel.DoWorkEventHandler(bgw_TcpPortLisen_DoWork); 60 } 61 62 /// <summary> 63 /// 后台异步对象动作 64 /// </summary> 65 /// <param name="sender"></param> 66 /// <param name="e"></param> 67 private void bgw_TcpPortLisen_DoWork(object sender, DoWorkEventArgs e) 68 { 69 try 70 { 71 TCPListener(TcpIp, TcpPort); 72 } 73 catch 74 { 75 MessageBoxResult result = MessageBox.Show("侦听端口已经被占用,请检查!", "警告", 76 MessageBoxButton.OKCancel, MessageBoxImage.Error); 77 if (result == MessageBoxResult.OK) 78 { 79 ListenerStop(); 80 TCPListener(TcpIp, TcpPort); 81 } 82 else 83 { 84 ListenerStop(); 85 this.Close(); 86 } 87 } 88 } 89 /// <summary> 90 /// 监听方法 91 /// </summary> 92 /// <param name="LisenIP"></param> 93 /// <param name="LisenPort"></param> 94 private void TCPListener(string LisenIP, int LisenPort) 95 { 96 TCPlis = new TcpListener(IPAddress.Parse(LisenIP), LisenPort);//在LisenIP:LisenPort新建一个TcpListener对象 97 TCPlis.Start(); 98 99 while (true)//开始监听 100 { 101 Socket s = TCPlis.AcceptSocket(); 102 103 string remote = s.RemoteEndPoint.ToString(); 104 105 Byte[] stream = new Byte[80]; 106 107 int i = s.Receive(stream);//接受连接请求的字节流 108 109 var mettingInfo = remote.Split(':'); 110 111 //端口接收信息 112 var arry = System.Text.Encoding.UTF8.GetString(stream); 113 114 MessageBox.Show(arry.ToString()); 115 116 // 发送Response 117 IPHostEntry hostEntry = Dns.GetHostEntry(mettingInfo[0]); 118 IPAddress ipAdress = null; 119 foreach (var ipd in hostEntry.AddressList) 120 { 121 if (ipd.ToString().Length <= 15) 122 { 123 ipAdress = ipd; 124 } 125 } 126 IPEndPoint endPoint = new IPEndPoint(ipAdress, Convert.ToInt32(mettingInfo[1])); 127 string body = "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n" + 128 "<xmlRoot><Appoint Results=\"T\"/></xmlRoot>"; 129 130 string sssss = "HTTP/1.1 200 OK\r\n" + 131 "Connection: close\r\n" + 132 "Content-Type:text/xml\r\n" + 133 "Content-Length:" + body.Length + 134 "\r\n\r\n" + 135 body; 136 Byte[] sendStream = new Byte[1024]; 137 sendStream = Encoding.UTF8.GetBytes(sssss); 138 s.SendTo(sendStream, endPoint); 139 } 140 } 141 /// <summary> 142 /// 停止监听 143 /// </summary> 144 private void ListenerStop() 145 { 146 TCPlis.Stop(); 147 TCPth.Abort();//终止线程 148 149 } 150 /// <summary> 151 /// 开始监听按钮 152 /// </summary> 153 /// <param name="sender"></param> 154 /// <param name="e"></param> 155 private void button1_Click(object sender, RoutedEventArgs e) 156 { 157 Match ipM = Regex.Match(this.txt_IP.Text.Trim(), IpRegex); 158 if (!ipM.Success) // 输入的IP 159 { 160 MessageBox.Show("IP输入错误!"); 161 return; 162 } 163 Match PortM = Regex.Match(this.txt_Port.Text.Trim(), PortRegex); 164 if (!PortM.Success) // 输入的IP 165 { 166 MessageBox.Show("Port输入错误!"); 167 return; 168 } 169 TcpIp = this.txt_IP.Text.Trim(); 170 TcpPort = Convert.ToInt32(this.txt_Port.Text.Trim()); 171 bgw_TcpPortLisen.RunWorkerAsync(); 172 } 173 /// <summary> 174 /// 停止监听按钮 175 /// </summary> 176 /// <param name="sender"></param> 177 /// <param name="e"></param> 178 private void button2_Click(object sender, RoutedEventArgs e) 179 { 180 ListenerStop(); 181 bgw_TcpPortLisen.CancelAsync(); 182 } 183 } 184 }