C#开发的简单端口转发程序的代码

下面代码是关于C#开发的简单端口转发程序的代码。

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace portmap_net
{
    sealed internal class state
    {

        #region Fields (5)

        public int _connect_cnt;
        public string _point_in;
        public string _point_out;
        public const string _print_head = "输入IP              输出IP              状态    连接数    接收/发送";
        public bool _running;
        public long _bytes_send;
        public long _bytes_recv;

        #endregion Fields

        #region Constructors (1)

        public state(string point_in, string point_out, bool running, int connect_cnt, int bytes_send, int bytes_recv)
        {
            _point_in = point_in;
            _point_out = point_out;
            _running = running;
            _connect_cnt = connect_cnt;
            _bytes_recv = bytes_recv;
            _bytes_send = bytes_send;
        }

        #endregion Constructors

        #region Methods (1)

        public override string ToString()
        {
            return string.Format("{0}{1}{2}{3}{4}", _point_in.PadRight(20, ' '), _point_out.PadRight(20, ' '), (_running ? "运行中  " : "启动失败"), _connect_cnt.ToString().PadRight(10, ' '), Math.Round((double)_bytes_recv / 1024) + "k/" + Math.Round((double)_bytes_send / 1024) + "k");
        }

        #endregion Methods
    }

    internal struct work_item
    {

        #region Data Members (4)

        public int _id;
        public EndPoint _ip_in;
        public string _ip_out_host;
        public ushort _ip_out_port;

        #endregion Data Members
    }

    sealed internal class program
    {

        #region Fields (4)

        private static StringBuilder _console_buf = new StringBuilder();
        private static readonly Dictionary<int, state> _state_dic = new Dictionary<int, state>();
        #endregion Fields

        #region Methods (8)

        private static void Main()
        {
            List<work_item> maps_list = new List<work_item>{
                new work_item{_id = 1, _ip_in = new IPEndPoint(IPAddress.Any,2012), _ip_out_host="10.10.1.18", _ip_out_port = 3389 },
                new work_item{_id = 2, _ip_in = new IPEndPoint(IPAddress.Any,2013), _ip_out_host="www.beta-1.cn", _ip_out_port = 80 }
            };

            foreach (var map_item in maps_list)
                map_start(map_item);

            Console.CursorVisible = false;
            while (true)
            {
                show_state();
                Thread.Sleep(2000);
            }
        }

        private static void map_start(work_item work)
        {
            Socket sock_svr = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            bool start_error = false;
            try
            {
                sock_svr.Listen(10);
            }
            catch (Exception)
            {
                start_error = true;
            }
            finally
            {
                _state_dic.Add(work._id, new state(work._ip_in.ToString(), work._ip_out_host + ":" + work._ip_out_port, !start_error, 0, 0, 0));
            }
        }

        private static void on_local_connected(IAsyncResult ar)
        {
            object[] ar_arr = ar.AsyncState as object[];
            Socket sock_svr = ar_arr[0] as Socket;
            work_item work = (work_item)ar_arr[1];

            ++_state_dic[work._id]._connect_cnt;
            Socket sock_cli = sock_svr.EndAccept(ar);
            sock_svr.BeginAccept(on_local_connected, ar.AsyncState);
            Socket sock_cli_remote = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                sock_cli_remote.Connect(work._ip_out_host, work._ip_out_port);
            }
            catch (Exception)
            {
                try
                {
                    sock_cli.Shutdown(SocketShutdown.Both);
                    sock_cli_remote.Shutdown(SocketShutdown.Both);
                    sock_cli.Close();
                    sock_cli_remote.Close();
                }
                catch (Exception)
                { }
                --_state_dic[work._id]._connect_cnt;
                return;
            }
            Thread t_send = new Thread(recv_and_send_caller) { IsBackground = true };
            Thread t_recv = new Thread(recv_and_send_caller) { IsBackground = true };
            t_send.Start(new object[] { sock_cli, sock_cli_remote, work._id, true });
            t_recv.Start(new object[] { sock_cli_remote, sock_cli, work._id, false });
            t_send.Join();
            t_recv.Join();
            --_state_dic[work._id]._connect_cnt;
        }

        private static void recv_and_send(Socket from_sock, Socket to_sock, Action<int> send_complete)
        {
            byte[] recv_buf = new byte[4096];
            int recv_len;
            while ((recv_len = from_sock.Receive(recv_buf)) > 0)
            {
                to_sock.Send(recv_buf, 0, recv_len, SocketFlags.None);
                send_complete(recv_len);
            }
        }

        private static void recv_and_send_caller(object thread_param)
        {
            object[] param_arr = thread_param as object[];
            Socket sock1 = param_arr[0] as Socket;
            Socket sock2 = param_arr[1] as Socket;
            try
            {
                recv_and_send(sock1, sock2, bytes =>
                {
                    state stat = _state_dic[(int)param_arr[2]];
                    if ((bool)param_arr[3])
                        stat._bytes_send += bytes;
                    else
                        stat._bytes_recv += bytes;
                });
            }
            catch (Exception)
            {
                try
                {
                    sock1.Shutdown(SocketShutdown.Both);
                    sock2.Shutdown(SocketShutdown.Both);
                    sock1.Close();
                    sock2.Close();
                }
                catch (Exception) { }
            }
        }

        private static void show_state()
        {
            StringBuilder curr_buf = new StringBuilder();
            curr_buf.AppendLine(program_ver);
            curr_buf.AppendLine(state._print_head);
            foreach (KeyValuePair<int, state> item in _state_dic)
                curr_buf.AppendLine(item.Value.ToString());
            if (_console_buf.Equals(curr_buf))
                return;
            Console.Clear();
            Console.WriteLine(curr_buf);
            _console_buf = curr_buf;
        }

        #endregion Methods
--------------------------------------------------";
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本软件由服务端 、 客户端和采集端三部分组成,用于将采集端计算机上的 TCP 端口映射 到客户端计算机 上,使 客户端计算机上的应用软件可以像访问本机上的 TCP 端口一样访问采 集端计算机上的 TCP 端口。注:采集端也被称作监测点。 本软件的采集端可以运行在 X86-Linux 、 ARM7-ucLinux 或 Windows 2000/XP 系统 上,本软件的客户端和服务端只能运行在 Windows 2000/XP 系统上。 本软件要解决的问题:如下图所示,采集端计算机(采集端 1)是一台运行 Linux 操作系 统的X86 嵌入式计算机,通过ADSL 接入Internet,该计算机上开有Telnet服务(TCP-23) 。 因网络设备限制,只允许该计算机访问外界计算机,而外界计算机无法访问该计算机的 TCP- 23 端口。客户端计算机(客户端 3)是某公司内部网络中的一台运行 Windows2000 操作系 统的计算机,通过公司的交换机接入 Internet。因为采集端计算机网络设备的限制,客户端 计算机无法访问采集端计算机上的 Telnet 服务。 为使采集端计算机上的 Telnet 服务可被客户端计算机 访问,在 客户端计算机上运行 TCP 中转站客户端软件,在采集端计算机上运行 TCP 中转站采集端软件。运行 TCP 中转站服务 端软件的服务器,是一台运行 Windows2000 系统有公网 IP 的计算机,客户端计算机和采 集端计算机均可以访问该服务器。 TCP 中转站软件将把采集端计算机的 TCP-23 端口映射到客户端计算机上,使用客户端 计算机的操作者用 Telnet 命令或 PuTTY 软件访问本机的 TCP-23 端口,即可与采集端计算 机的 TCP-23(Telnet 服务)通讯。每个客户端计算机可以映射多个采集端计算机的多个 TCP 端口,在客户端计算机上为每个映射的采集端计算机分配一个私有 IP:127.1.0.X 。例如: 客户端计算机与三台采集端计算机建立了映射,则这三台采集端计算机分别映射到这台客户 端计算机的 127.1.0.11、127.1.0.12 和 127.1.0.13 三个私有 IP 地址上,如果客户端计 算机上的应用软件(例如 PuTTY)访问本台计算机私有 IP 127.1.0.11 的 TCP23 端口,则应 用软件(PuTTY)实际访问的是采集端计算机 1 的 TCP-23 端口。
C# 中实现端口转发可以使用 TcpListener 和 TcpClient 类,而断点传输文件可以使用 FileStream 和 BinaryReader/BinaryWriter 类。 以下是一个简单的示例代码,演示了如何在本地端口监听并转发传入的连接: ```csharp using System; using System.IO; using System.Net; using System.Net.Sockets; class PortForwarder { static void Main(string[] args) { int localPort = 1234; // 本地监听端口 string remoteHost = "example.com"; // 转发目标主机 int remotePort = 5678; // 转发目标端口 TcpListener listener = new TcpListener(IPAddress.Any, localPort); listener.Start(); Console.WriteLine("Listening on port " + localPort); while (true) { TcpClient client = listener.AcceptTcpClient(); Console.WriteLine("Accepted connection from " + client.Client.RemoteEndPoint); TcpClient remoteClient = new TcpClient(remoteHost, remotePort); Console.WriteLine("Connected to remote host " + remoteHost + ":" + remotePort); // 开启一个后台线程,将两个连接之间的数据进行转发 System.Threading.Thread thread = new System.Threading.Thread(() => { try { using (var localStream = client.GetStream()) using (var remoteStream = remoteClient.GetStream()) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = localStream.Read(buffer, 0, buffer.Length)) > 0) { remoteStream.Write(buffer, 0, bytesRead); } } } catch (Exception ex) { Console.WriteLine("Error: " + ex.ToString()); } finally { client.Dispose(); remoteClient.Dispose(); } }); thread.IsBackground = true; thread.Start(); } } } ``` 要实现断点传输文件,可以根据需要进行读取和写入文件的偏移量,并在 TcpClient 之间进行数据传输。以下是一个简单的示例代码: ```csharp using System; using System.IO; using System.Net; using System.Net.Sockets; class FileTransfer { static void Main(string[] args) { string localFilePath = "localfile.dat"; // 本地文件路径 string remoteHost = "example.com"; // 文件接收主机 int remotePort = 5678; // 文件接收端口 long offset = 0; // 起始偏移量 TcpClient client = new TcpClient(remoteHost, remotePort); Console.WriteLine("Connected to remote host " + remoteHost + ":" + remotePort); using (var fileStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(fileStream)) using (var writer = new BinaryWriter(client.GetStream())) { // 将文件读取指定偏移量 fileStream.Seek(offset, SeekOrigin.Begin); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0) { writer.Write(buffer, 0, bytesRead); offset += bytesRead; Console.WriteLine("Sent " + bytesRead + " bytes at offset " + offset); } } client.Dispose(); } } ``` 注意,以上代码仅为示例,实际应用中需要考虑错误处理、超时、流关闭等情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值