积极答复者
请教一个功能实现:通过程序,转发特定端口的数据

问题
答案
-
这是测试代码,目的是把程序运行所在机器的89号端口中继到202.103.11.22的80端口上: class Program { static void Main(string[] args) { Console.WriteLine("start : start test"); Console.WriteLine("stop : stop test"); Console.WriteLine("quit : quit this program"); RelayListener relay = new RelayListener(); relay.Port = 89; relay.DestIP = IPAddress.Parse("202.103.11.22"); relay.DestPort = 80; relay.AddAllowIP("127.0.0.1"); string strRead; do { Console.Write(">"); strRead = Console.ReadLine(); if (strRead == "start") { relay.Start(); Console.WriteLine("Start at port {0} -> {1}:{2}", relay.Port, relay.DestIP, relay.DestPort); } else if (strRead == "stop") { relay.Stop(); Console.WriteLine("Listener has stopped."); } } while (strRead != "quit"); } }
下面是中继监听器的实现: public class RelayListener { public RelayListener() { m_evCanExit = new EventWaitHandle(false, EventResetMode.ManualReset); m_actListen = Listen; m_epDest = new IPEndPoint(IPAddress.None, 0); //m_confirm = new SecurityConfirm(); m_listSR = new List<SocketRelay>(); } // 中继侦听端口 public int Port { get; set; } // 中继目标IP public IPAddress DestIP { get { return m_epDest.Address; } set { m_epDest.Address = value; } } // 中继目标端口 public int DestPort { get { return m_epDest.Port; } set { m_epDest.Port = value; } } public void AddAllowIP(string strIP) { //m_confirm.AddAllowIP(strIP); } public void Start() { lock (m_actListen) { // 已存在一个监听,避免重复开启 if ((m_arListen != null) && (!m_arListen.IsCompleted)) return; m_evCanExit.Reset(); m_arListen = m_actListen.BeginInvoke(null, null); } } public void Stop() { lock (m_actListen) { // 没有活动的监听 if (m_arListen == null || m_arListen.IsCompleted) return; m_evCanExit.Set(); m_actListen.EndInvoke(m_arListen); lock(m_listSR) m_listSR.Clear(); } } private void Listen() { EventWaitHandle evAccept = new EventWaitHandle(false, EventResetMode.ManualReset); // IPv4 TCP using (Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { IPEndPoint ep = new IPEndPoint(IPAddress.Any, Port); socketListener.Bind(ep); socketListener.Listen(5); WaitHandle[] waits = new WaitHandle[] { m_evCanExit, evAccept }; int nWait; // 等待结果 do { evAccept.Reset(); AsyncCallback ac = AcceptCallback; Tuple<Socket, EventWaitHandle> state = new Tuple<Socket, EventWaitHandle>(socketListener, evAccept); socketListener.BeginAccept(ac, state); nWait = WaitHandle.WaitAny(waits); } while (nWait != 0); socketListener.Close(); } } private void AcceptCallback(IAsyncResult ar) { Socket sktActive = null; try { var state = (Tuple<Socket, EventWaitHandle>)ar.AsyncState; state.Item2.Set(); sktActive = state.Item1.EndAccept(ar); } catch (ObjectDisposedException) { // Accept has been cancelled. return; } try { // 安全验证 //if (!m_confirm.Confirm(sktActive)) //{ // sktActive.Close(); // return; //} Socket sktPassive = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sktPassive.Connect(m_epDest); SocketRelay relay = new SocketRelay(sktActive, sktPassive); relay.OnFinished += OnSocketRelayFinished; relay.Run(); lock(m_listSR) m_listSR.Add(relay); } catch (SocketException ex) { string strbuf = String.Format("{0}({1})", ex.Message, ex.ErrorCode); byte[] buf = Encoding.Default.GetBytes(strbuf); sktActive.Send(buf); sktActive.Shutdown(SocketShutdown.Both); sktActive.Close(); } } private void OnSocketRelayFinished(SocketRelay item) { lock (m_listSR) { if(m_listSR.Contains(item)) m_listSR.Remove(item); } } // 侦听Action private Action m_actListen; // 侦听异步结果 private IAsyncResult m_arListen; // 退出事件 private EventWaitHandle m_evCanExit; // 中继目的 private IPEndPoint m_epDest; // 安全验证 //private SecurityConfirm m_confirm; // 保持对活动连接的引用 private List<SocketRelay> m_listSR; }
你最关心的中继实现:// 包含1对Socket,实现数据传送中继 class SocketRelay { public SocketRelay(Socket act, Socket pass) { m_sktActive = act; m_sktPassive = pass; } public void Run() { // 把从Passive收到的,发送给Active RecvSend(m_sktPassive, m_sktActive); // 把从Active收到的,发送给Passive RecvSend(m_sktActive, m_sktPassive); } public Action<SocketRelay> OnFinished; private void RecvSend(Socket sktRecv, Socket sktSend) { RecvPack pack = new RecvPack(); pack.sktRecv = sktRecv; pack.sktSend = sktSend; AsyncCallback ac = RecvCallback; sktRecv.BeginReceive(pack.buf, 0, pack.buf.Length, SocketFlags.None, ac, pack); } private void RecvCallback(IAsyncResult ar) { try { // 1.接收 RecvPack pack = (RecvPack)ar.AsyncState; int nRecv = pack.sktRecv.EndReceive(ar); if (nRecv > 0) { // 2.复制 RecvPack packSend = new RecvPack(); packSend.sktSend = pack.sktSend; Array.Copy(pack.buf, packSend.buf, nRecv); // 3.发送 AsyncCallback ac = SendCallback; pack.sktSend.BeginSend(packSend.buf, 0, nRecv, SocketFlags.None, ac, packSend); // 4.再接收 AsyncCallback acRecv = RecvCallback; pack.sktRecv.BeginReceive(pack.buf, 0, pack.buf.Length, SocketFlags.None, acRecv, pack); } else { // 5.关闭连接 pack.sktSend.Shutdown(SocketShutdown.Both); pack.sktSend.Close(); pack.sktRecv.Shutdown(SocketShutdown.Both); pack.sktRecv.Close(); if (OnFinished != null) OnFinished(this); } } catch (SocketException) { // Cancelled 对端关闭了连接 if (OnFinished != null) OnFinished(this); } catch (ObjectDisposedException) { // Cancelled if (OnFinished != null) OnFinished(this); } } private void SendCallback(IAsyncResult ar) { try { RecvPack pack = (RecvPack)ar.AsyncState; int nSent = pack.sktSend.EndSend(ar); } catch (SocketException) { // Cancelled 对端关闭了连接 if (OnFinished != null) OnFinished(this); } catch (ObjectDisposedException) { // Cancelled if (OnFinished != null) OnFinished(this); } } // 主动端,即主动发起连接的一端 private Socket m_sktActive; // 被动端 private Socket m_sktPassive; } class RecvPack { public RecvPack() { buf = new byte[1024 * 128]; // 128k } public Socket sktRecv; public Socket sktSend; public byte[] buf; }
- 已标记为答案 Lie YouModerator 2011年6月13日 5:25
全部回复
-
这个问题太有难度了。楼主现在做到哪一步了?
别告诉说只有这个想法,什么代码都没写啊。
个人建议: 这玩意都是经验累积的。估计在这个地方有牛人,但是贡献代码的可能性。。。
很期待有人给代码和相关资料。不过还是建议先一步一步的来。
找不到下手的地方 求思路的(我也不是伸手党,但是有这个想法 但是不知道应该用什么技术实现) 没有代码也无所谓 给点提示我目前不知道如何连接两个端口转发原始数据,如果这点想不通就没法开始写代码.本人技术确实很菜,做个聊天室没问题,没做过高级的TCP/IP开发.对此一点思路都没有
楼上可能没看清我的最后一句话,主要是给思路,如果最佳。。“这个程序应该用什么技术做,如果能提供一下关键代码/资料最佳”
- 已编辑 SummerYa 2011年4月28日 3:02 补充内容
-
国内类似功能的就是Oray开发的向日葵。
它里面有个功能叫“远程应用”:能够将远程主机的端口转发到本地主机
这里我将它简化了,不需要涉及P2P打洞之类的,只需要将一个端口映射为另外一个端口即可
- 已标记为答案 Lie YouModerator 2011年6月13日 5:25
- 取消答案标记 Lie YouModerator 2011年6月13日 5:25
-
-
这是测试代码,目的是把程序运行所在机器的89号端口中继到202.103.11.22的80端口上: class Program { static void Main(string[] args) { Console.WriteLine("start : start test"); Console.WriteLine("stop : stop test"); Console.WriteLine("quit : quit this program"); RelayListener relay = new RelayListener(); relay.Port = 89; relay.DestIP = IPAddress.Parse("202.103.11.22"); relay.DestPort = 80; relay.AddAllowIP("127.0.0.1"); string strRead; do { Console.Write(">"); strRead = Console.ReadLine(); if (strRead == "start") { relay.Start(); Console.WriteLine("Start at port {0} -> {1}:{2}", relay.Port, relay.DestIP, relay.DestPort); } else if (strRead == "stop") { relay.Stop(); Console.WriteLine("Listener has stopped."); } } while (strRead != "quit"); } }
下面是中继监听器的实现: public class RelayListener { public RelayListener() { m_evCanExit = new EventWaitHandle(false, EventResetMode.ManualReset); m_actListen = Listen; m_epDest = new IPEndPoint(IPAddress.None, 0); //m_confirm = new SecurityConfirm(); m_listSR = new List<SocketRelay>(); } // 中继侦听端口 public int Port { get; set; } // 中继目标IP public IPAddress DestIP { get { return m_epDest.Address; } set { m_epDest.Address = value; } } // 中继目标端口 public int DestPort { get { return m_epDest.Port; } set { m_epDest.Port = value; } } public void AddAllowIP(string strIP) { //m_confirm.AddAllowIP(strIP); } public void Start() { lock (m_actListen) { // 已存在一个监听,避免重复开启 if ((m_arListen != null) && (!m_arListen.IsCompleted)) return; m_evCanExit.Reset(); m_arListen = m_actListen.BeginInvoke(null, null); } } public void Stop() { lock (m_actListen) { // 没有活动的监听 if (m_arListen == null || m_arListen.IsCompleted) return; m_evCanExit.Set(); m_actListen.EndInvoke(m_arListen); lock(m_listSR) m_listSR.Clear(); } } private void Listen() { EventWaitHandle evAccept = new EventWaitHandle(false, EventResetMode.ManualReset); // IPv4 TCP using (Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { IPEndPoint ep = new IPEndPoint(IPAddress.Any, Port); socketListener.Bind(ep); socketListener.Listen(5); WaitHandle[] waits = new WaitHandle[] { m_evCanExit, evAccept }; int nWait; // 等待结果 do { evAccept.Reset(); AsyncCallback ac = AcceptCallback; Tuple<Socket, EventWaitHandle> state = new Tuple<Socket, EventWaitHandle>(socketListener, evAccept); socketListener.BeginAccept(ac, state); nWait = WaitHandle.WaitAny(waits); } while (nWait != 0); socketListener.Close(); } } private void AcceptCallback(IAsyncResult ar) { Socket sktActive = null; try { var state = (Tuple<Socket, EventWaitHandle>)ar.AsyncState; state.Item2.Set(); sktActive = state.Item1.EndAccept(ar); } catch (ObjectDisposedException) { // Accept has been cancelled. return; } try { // 安全验证 //if (!m_confirm.Confirm(sktActive)) //{ // sktActive.Close(); // return; //} Socket sktPassive = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sktPassive.Connect(m_epDest); SocketRelay relay = new SocketRelay(sktActive, sktPassive); relay.OnFinished += OnSocketRelayFinished; relay.Run(); lock(m_listSR) m_listSR.Add(relay); } catch (SocketException ex) { string strbuf = String.Format("{0}({1})", ex.Message, ex.ErrorCode); byte[] buf = Encoding.Default.GetBytes(strbuf); sktActive.Send(buf); sktActive.Shutdown(SocketShutdown.Both); sktActive.Close(); } } private void OnSocketRelayFinished(SocketRelay item) { lock (m_listSR) { if(m_listSR.Contains(item)) m_listSR.Remove(item); } } // 侦听Action private Action m_actListen; // 侦听异步结果 private IAsyncResult m_arListen; // 退出事件 private EventWaitHandle m_evCanExit; // 中继目的 private IPEndPoint m_epDest; // 安全验证 //private SecurityConfirm m_confirm; // 保持对活动连接的引用 private List<SocketRelay> m_listSR; }
你最关心的中继实现:// 包含1对Socket,实现数据传送中继 class SocketRelay { public SocketRelay(Socket act, Socket pass) { m_sktActive = act; m_sktPassive = pass; } public void Run() { // 把从Passive收到的,发送给Active RecvSend(m_sktPassive, m_sktActive); // 把从Active收到的,发送给Passive RecvSend(m_sktActive, m_sktPassive); } public Action<SocketRelay> OnFinished; private void RecvSend(Socket sktRecv, Socket sktSend) { RecvPack pack = new RecvPack(); pack.sktRecv = sktRecv; pack.sktSend = sktSend; AsyncCallback ac = RecvCallback; sktRecv.BeginReceive(pack.buf, 0, pack.buf.Length, SocketFlags.None, ac, pack); } private void RecvCallback(IAsyncResult ar) { try { // 1.接收 RecvPack pack = (RecvPack)ar.AsyncState; int nRecv = pack.sktRecv.EndReceive(ar); if (nRecv > 0) { // 2.复制 RecvPack packSend = new RecvPack(); packSend.sktSend = pack.sktSend; Array.Copy(pack.buf, packSend.buf, nRecv); // 3.发送 AsyncCallback ac = SendCallback; pack.sktSend.BeginSend(packSend.buf, 0, nRecv, SocketFlags.None, ac, packSend); // 4.再接收 AsyncCallback acRecv = RecvCallback; pack.sktRecv.BeginReceive(pack.buf, 0, pack.buf.Length, SocketFlags.None, acRecv, pack); } else { // 5.关闭连接 pack.sktSend.Shutdown(SocketShutdown.Both); pack.sktSend.Close(); pack.sktRecv.Shutdown(SocketShutdown.Both); pack.sktRecv.Close(); if (OnFinished != null) OnFinished(this); } } catch (SocketException) { // Cancelled 对端关闭了连接 if (OnFinished != null) OnFinished(this); } catch (ObjectDisposedException) { // Cancelled if (OnFinished != null) OnFinished(this); } } private void SendCallback(IAsyncResult ar) { try { RecvPack pack = (RecvPack)ar.AsyncState; int nSent = pack.sktSend.EndSend(ar); } catch (SocketException) { // Cancelled 对端关闭了连接 if (OnFinished != null) OnFinished(this); } catch (ObjectDisposedException) { // Cancelled if (OnFinished != null) OnFinished(this); } } // 主动端,即主动发起连接的一端 private Socket m_sktActive; // 被动端 private Socket m_sktPassive; } class RecvPack { public RecvPack() { buf = new byte[1024 * 128]; // 128k } public Socket sktRecv; public Socket sktSend; public byte[] buf; }
- 已标记为答案 Lie YouModerator 2011年6月13日 5:25