求救
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Collections;
using System.Threading;namespace HttpProxyDemo
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }        private void MainForm_Load(object sender, EventArgs e)
        {
           
        }        int ProxyPort;
        /// <summary>
        /// 启动Http代理服务器
        /// </summary>
        public void MainStart()
        {
            TcpListener tcplistener = null;
            try
            {
                // 开始监听端口
                tcplistener = new TcpListener(IPAddress.Parse("127.0.0.1"), ProxyPort);//Dns.GetHostAddresses(Dns.GetHostName())[0]
                tcplistener.Start();
                //Console.WriteLine("侦听端口号: " + ProxyPort.ToString());
                this.richTextBox1.AppendText("侦听端口号: " + ProxyPort.ToString());
            }
            catch (Exception e)
            {
                this.richTextBox1.AppendText("启动代理服务器失败: " + e.Message);
            }
            while (true)
            {
                try
                {
                    // 接受客户端连接
                    Socket socket = tcplistener.AcceptSocket();
                    //************上面卡死*******************             
                    // 启动新线程,处理连接
                    ClientSocket = socket;
                    Thread thread = new Thread(new ThreadStart(Start));
                    thread.Start();
                }
                catch (Exception e)
                {                    this.richTextBox1.AppendText("接受客户端连接异常:" + e.Message);
                }
            }
        }         // 客户端socket
        Socket ClientSocket;
        // 设定编码
        Encoding Default = Encoding.GetEncoding("gb2312");
 
        public void Start()
        {
            // 客户端缓冲区,读取客户端命令
            Byte[] ReadBuff = new byte[1024 * 10];
            try
            {
                int Length = ClientSocket.Receive(ReadBuff);
                // 没有读到数据
                if (0 == Length)
                {
                    this.richTextBox1.AppendText("从客户端读取命令错误");
                    ClientSocket.Shutdown(SocketShutdown.Both);
                    ClientSocket.Close();
                    return;
                }
            }
            // 读取出现异常
            catch (Exception e)
            {                this.richTextBox1.AppendText("读取客户端异常:" + e.Message);
            }
            // 来自客户端的HTTP请求字符串
            string ClientMsg = Default.GetString(ReadBuff);
            // 根据rnrn截取请求行
            //string Line = ClientMsg.Substring(0, ClientMsg.IndexOf("rn"));
            //string[] CmdArray = Line.Split(' ');
            // GET http://www.test.com:80/index.php HTTP/1.1
            // CONNECT www.test.com:443 HTTP/1.1
            //string Cmd = CmdArray[0];
            //string RawUrl = CmdArray[1];
            string RawUrl = "http://86.108.17.138";            this.richTextBox1.AppendText("原始请求: "+ ClientMsg);            // GET,POST和其他
            DoOther(RawUrl, ClientMsg);
        }        /// <summary>
        /// 处理GET,POST等命令。使用了POLL,在代理服务器中强制去掉了Keep-Alive能力
        /// </summary>
        /// <param name="RawUrl"></param>
        /// <param name="ClientMsg"></param>
        public void DoOther(string RawUrl, string ClientMsg)
        {
            RawUrl = RawUrl.Substring(0 + "http://".Length);
            int Port;
            string Host;
            string Url;
            // 下面是分割处理请求,此处应该用正则匹配,不过我不擅长,因此手动切割,—_—!
            int index1 = RawUrl.IndexOf(':');
            // 没有端口
            if (index1 == -1)
            {
                Port = 80;
                int index2 = RawUrl.IndexOf('/');
                // 没有目录
                if (index2 == -1)
                {
                    Host = RawUrl;
                    Url = "/";
                }
                else
                {
                    Host = RawUrl.Substring(0, index2);
                    Url = RawUrl.Substring(index2);
                }
            }
            else
            {
                int index2 = RawUrl.IndexOf('/');
                // 没有目录
                if (index2 == -1)
                {
                    Host = RawUrl.Substring(0, index1);
                    Port = Int32.Parse(RawUrl.Substring(index1 + 1));
                    Url = "/";
                }
                else
                {
                    // /出现在:之前,则说明:后面的不是端口
                    if (index2 < index1)
                    {
                        Host = RawUrl.Substring(0, index2);
                        Port = 80;
                    }
                    else
                    {
                        Host = RawUrl.Substring(0, index1);
                        Port = Int32.Parse(RawUrl.Substring(index1 + 1, index2 - index1 - 1));
                    }
                    Url = RawUrl.Substring(index2);
                }
            }
            Console.WriteLine("Host is:{0}, Port is:{1}, Url is:{2}", Host, Port, Url);
            IPAddress[] address = null;
            try
            {
                IPHostEntry IPHost = Dns.GetHostEntry(Host);
                address = IPHost.AddressList;
                this.richTextBox1.AppendText("Web服务器IP地址: " + address[0]);
            }
            catch (Exception e)
            {
                this.richTextBox1.AppendText("解析服务器地址异常: " + e.Message);
            }            Socket IPsocket = null;            try
            {
                // 连接到真实WEB服务器
                IPEndPoint ipEndpoint = new IPEndPoint(address[0], Port);
                IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPsocket.Connect(ipEndpoint);
                // 对WEB服务器端传送HTTP请求命令,将原始HTTP请求中HTTP PROXY部分包装去掉
                string ReqData = ClientMsg;
                // 改写头中的URL,从http://www.test.com/index.php改为/index.php
                ReqData = ReqData.Replace("http://" + RawUrl, Url);
                // 按照rn切分HTTP头
                string[] ReqArray = ReqData.Split(new string[1] { "rn" }, StringSplitOptions.None);
                ReqData = "";
                // 改写Keep-Alive等字段
                for (int index = 0; index < ReqArray.Length; index++)
                {
                    if (ReqArray[index].StartsWith("Proxy-Connection:"))
                    {
                        ReqArray[index] = ReqArray[index].Replace("Proxy-Connection:", "Connection:");
                    }
                    // 修改后的字段组合成请求
                    if (ReqArray[index] != "")
                    {
                        ReqData = ReqData + ReqArray[index] + "rn";
                    }
                }
                ReqData = ReqData.Trim();
                byte[] SendBuff = Default.GetBytes(ReqData);
                IPsocket.Send(SendBuff);
            }
            catch (Exception e)
            {
                this.richTextBox1.AppendText("发送请求到服务器异常: " + e.Message);
            }
            // 使用Poll来判断完成,某些站点会出问题
            while (true)
            {
                Byte[] RecvBuff = new byte[1024 * 20];
                try
                {
                    if (!IPsocket.Poll(15 * 1000 * 1000, SelectMode.SelectRead))
                    {
                        this.richTextBox1.AppendText("HTTP超时,关闭连接");
                        break;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Poll: {0}" + e.Message);
                    break;
                }                int Length = 0;
                try
                {
                    Length = IPsocket.Receive(RecvBuff);
                    if (0 == Length)
                    {
                        this.richTextBox1.AppendText("服务端关闭");
                        break;
                    }                    //Console.WriteLine("从服务端收到字节:{0}", Length);
                    this.richTextBox1.AppendText("从服务端收到字节:" + Length);
                   // Console.WriteLine("内容:{0}", Encoding.Default.GetString(RecvBuff));
                }
                catch (Exception e)
                {
                    this.richTextBox1.AppendText("Recv: " + e.Message);
                    break;
                }
                try
                {
                    Length = ClientSocket.Send(RecvBuff, Length, 0);
                   // Console.WriteLine("发送字节到客户端:{0}", Length);
                    this.richTextBox1.AppendText("发送字节到客户端:" + Length);
                }
                catch (Exception e)
                {
                    //Console.WriteLine("Send: " + e.Message);
                    this.richTextBox1.AppendText("Send: " + e.Message);
                }
            }
            try
            {
                ClientSocket.Shutdown(SocketShutdown.Both);
                ClientSocket.Close();
                IPsocket.Shutdown(SocketShutdown.Both);
                IPsocket.Close();
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.Message);
            }
        }        private void btn_set_Click(object sender, EventArgs e)
        {
            this.ProxyPort = int.Parse(this.clientPort.Text);
            MainStart();
        }    }
}

解决方案 »

  1.   

    MainStart函数要在线程里启动,即btn_set_Click事件里开线程启动MainStart()
    你想想,你的MainStart函数是个while(true)循环监听,不开线程当然会卡了
      

  2.   

    tcplistener.AcceptSocket();是打开监听了,但你得扔一个线程出来,在这个线程里打开监听,而不是打开监听,扔一个线程接收数据。
      

  3.   

    调试过了。每次去到
    tcplistener.AcceptSocket();
    都卡死,下面无法执行!!!!
      

  4.   

    private void btn_set_Click(object sender, EventArgs e)
            {
    this.ProxyPort = int.Parse(this.clientPort.Text);
    Thread thread = new Thread(new ThreadStart(Start111));
                        thread.Start();                    } void Start111()
    {
         MainStart();
    }
    大概思路是这样写!
    还有tcplistener.AcceptSocket();这句就是要阻塞接收,没有消息会一直阻塞下去。所以你要开线程还有线程中如果要访问界面控件的话用委托
      

  5.   

    比如 
    private void button1_Click(object sender, EventArgs e)
            {
                Thread threadStart;
                threadStart = new Thread(new ThreadStart(WaitingOpen));//
                threadStart.Priority = ThreadPriority.Highest;
                threadStart.Start();
            }
            private delegate void InvokeDelegate1();
            public void WaitingOpen()
            {            if (this.InvokeRequired)
                    this.BeginInvoke(new InvokeDelegate1(WaitingOpen_Fun));
            }
            private void WaitingOpen_Fun()
            {           在这里就可以访问并操作界面控件了,
                 把你MainStart函数内容写在这里
            }
      

  6.   

    打个广告,谁能帮我看看这个用新线程接收数据到textbox怎么依然阻塞