| namespace P2PTest { using System; using System.Net.Sockets; using System.Threading; public class Listener { private Thread th; private TcpListener tcpl; public bool listenerRun = true; //listenerRun为true,表示可以接受连接请求,false则为结束程序 public Listener()//构造函数 { th = new Thread(new ThreadStart(Listen));//新建一个用于监听的线程 th.Start();//打开新线程 } public void Stop() { tcpl.Stop(); th.Abort();//终止线程 } private void Listen() { try { tcpl = new TcpListener(5656);//在5656端口新建一个TcpListener对象 tcpl.Start(); Console.WriteLine("started listening.."); while(listenerRun)//开始监听 { Socket s = tcpl.AcceptSocket(); string remote = s.RemoteEndPoint.ToString(); Byte[] stream = new Byte[80]; int i=s.Receive(stream);//接受连接请求的字节流 string msg = "<" + remote + ">" + System.Text.Encoding.UTF8.GetString(stream); Console.WriteLine(msg);//在控制台显示字符串 } } catch(System.Security.SecurityException) { Console.WriteLine("firewall says no no to application - application cries.."); } catch(Exception) { Console.WriteLine("stoped listening.."); } } } } |
对Listen()函数的补充说明:
这个函数是Listener类的核心部分。该函数首先被构造函数调用。只要布尔值listenerRun为true,我们就可以在端口5656创建并开始一个Tcp监听对象TcpListener进行监听网络中的连接请求,而一旦listenerRun被置为false,则表示程序结束了。在循环体内部,我们先接受一个连接,用s.RemoteEndPoint获得它的IP地址并获得其字节流。根据获得的字节流,我们用UTF8编码将它转化为字符串。最后,我们就在控制台中显示获得的字符串。
对于catch语句,第一个块捕获一个可能由防火墙引起的例外。因为对于防火墙而言,它可能认为这是一个特洛依木马或是儒虫病毒什么的,所以就会拒绝通过。解决办法就是重新配置防火墙。第二个块用于捕获一般的例外,比如当我们调用了stop()函数后,我们销毁了TcpListener对象,那就自然不可能再进行监听了。
2.Sender类:
Sender类就一个函数,所以是相当简单的。
代码以及注释如下:
| namespace P2PTest { using System; using System.IO; using System.Net.Sockets; public class Sender { public void Send(string[] aInput) { string stream = ""; //获得要发送的信息 for(int i=2; i stream += aInput[i] + " "; } try { TcpClient tcpc = new TcpClient(aInput[1], 5656); //在5656端口新建一个TcpClient对象 NetworkStream tcpStream = tcpc.GetStream(); StreamWriter reqStreamW = new StreamWriter(tcpStream); reqStreamW.Write(stream); reqStreamW.Flush();//发送信息 tcpStream.Close(); tcpc.Close(); } catch(Exception) { Console.WriteLine("connection refused by target computer"); } } } } |
| namespace P2PTest { using System; public class InputHandler { public bool appRun = true;//当appRun为false时,程序结束 public InputHandler() { Console.WriteLine("type help for a list of commands."); Input(); } private static Listener li;//一个静态的Listener对象 private string inparam; private string[] aInput;//数组aInput用于接受用户输入的信息 public void Input() { while(appRun) { inparam = Console.ReadLine(); aInput = inparam.Split(' '); //将inparam分割的目的是为了获得字符串中的第一个字,从而执行以下不同的命令 switch(aInput[0]) { case "send"://如果是"send",则新建一个Sender对象并发送信息 Sender se = new Sender(); se.Send(aInput); break; case "start"://如果是"start",则新的开始监听 try { li.listenerRun = false; li.Stop(); } catch(NullReferenceException) { ; } finally { li = new Listener(); } break; case "stop"://如果是"stop",则停止监听 try { li.listenerRun = false; li.Stop(); } catch(NullReferenceException) { ; } break; case "exit"://退出程序 try { li.listenerRun = false; li.Stop(); } catch(NullReferenceException) { ; } finally { appRun = false; } break; case "help"://显示帮助信息 Console.WriteLine("Commands:"); Console.WriteLine("start: starts the listener"); Console.WriteLine("stop: stops the listener if started"); Console.WriteLine("send: send Console.WriteLine("exit: exits the application"); Console.WriteLine("help: you already know"); break; default: Console.WriteLine("Invalid command"); break; } } } } } |
4.Initialize类:
Initialize类进行程序的初始化工作,它新建了一个InputHandler对象,只要该对象的布尔值appRun为true,就一直运行之,直到该值为false,程序退出。
代码以及注释如下:
| namespace P2PTest { using System; public class Init { public static void Main() { InputHandler ih = new InputHandler();//新建一个InputHandler对象 while(ih.appRun);//直到ih.appRun为false,程序退出 Console.WriteLine("exiting.."); } } } |




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-630625/ ,如需转载,请注明出处,否则将追究法律责任。