关于网络编程,现代的编程语言都会涉及,这里给出的是一个小练习,可以实现局域网聊天。
关于异步调用,一个形象的例子在帖子VC中如何实现一个窗口显示几秒后自动关闭?中就被提出过了。Windows下运行的程序都不停地等待用户的指令(即消息),然后在自身的消息-响应映射表中循环,找到合适的处理函数来对这个消息作出响应。因此,如刷新界面,接受用户的键盘输入,显示菜单等等都需要由程序的主线程来完成。这就导致了windows程序的主线程不适宜被长时间的阻塞,在某些时候,这又是不可避免的,例如本例中的TcpListener,就需要建立新的线程来单独负责此事,然而新的线程在执行时有需要对界面进行操作,在本例中,是实时地显示接受到的消息。为了满足这一系列需求,在这个小练习中采用了.NET平台中提供的代理(delegate)技术,代理即C/C++中函数指针的拓展,参考资料多如牛毛,具体用法无须赘述,上例子吧。
[attach]48521[/attach]
流程图为:
[attach]48516[/attach]
代码:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Text;
- using System.Windows.Forms;
- using System.Threading;
- using System.Net;
- using System.Net.Sockets;
- namespace WindowsApplication1
- {
- public partial class Form1 : Form
- {
- /// <summary>
- /// 结束线程的标记
- /// </summary>
- public bool IsGoOn = true;
- /// <summary>
- /// 构造代理
- /// </summary>
- public delegate void Show_Rec_Delegate(String Msg);
- public delegate void Show_Stp_Delegate(int Ds);
- public delegate void Show_Sys_Delegate(String Msg);
- /// <summary>
- /// 通信层变量
- /// </summary>
- TcpListener server = null;
- public Form1()
- {
- InitializeComponent();
- }
- /// <summary>
- /// 开始发送内容
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void buttonOK_Click(object sender, EventArgs e)
- {
- try
- {
- TcpClient client = new TcpClient(Str_TargetIP.Text, Convert.ToInt16(Str_SendPort.Text));
- String message = UserName.Text +": " +MsgSend.Text;
- Byte[] data = System.Text.Encoding.Unicode.GetBytes(message);
- NetworkStream stream = client.GetStream();
- stream.Write(data, 0, data.Length);
- WriteSysMsg("Sent: " + message);
- WriteRecMsg(message);
- stream.Close();
- client.Close();
- MsgSend.Text = String.Empty;
- toolStripProgressBar1.Value += 1;
- }
- catch (ArgumentNullException ex)
- {
- WriteSysMsg("ArgumentNullException: "+ ex.Message);
- }
- catch (SocketException ex)
- {
- WriteSysMsg("SocketException: "+ ex.Message);
- }
- }
- /// <summary>
- /// 创建并启动监听线程
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Form1_Load(object sender, EventArgs e)
- {
- System.Net.IPAddress addr;
- // 获得本机局域网IP地址
- addr = new System.Net.IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address);
- LocalIP.Text = addr.ToString();
- }
- /// <summary>
- /// 用以将Msg显示在接收区域
- /// </summary>
- /// <param name="Msg"></param>
- public void WriteRecMsg(String Msg)
- {
- MsgRecieve.Text += System.DateTime.Now + Environment.NewLine + " " + Msg + Environment.NewLine;
- }
- /// <summary>
- /// 用以将Msg显示在系统消息区域
- /// </summary>
- /// <param name="Msg"></param>
- public void WriteSysMsg(String Msg)
- {
- MsgSys.Text = System.DateTime.Now + ":" + Environment.NewLine + " " + Msg + Environment.NewLine + MsgSys.Text;
- }
- /// <summary>
- /// 用以用进度条记录当前监听线程的进度
- /// </summary>
- public void WriteListenStep(int Ds)
- {
- toolStripProgressBar2.Value = (toolStripProgressBar1.Value + Ds) % 100;
- }
- /// <summary>
- /// UDP监听线程的实际操作函数
- /// </summary>
- public void UDP_Listener()
- {
- try
- {
- //实例化代理
- Show_Rec_Delegate Show_Rec = new Show_Rec_Delegate(this.WriteRecMsg);
- Show_Stp_Delegate Show_Stp = new Show_Stp_Delegate(this.WriteListenStep);
- Show_Sys_Delegate Show_Sys = new Show_Sys_Delegate(this.WriteSysMsg);
- this.Invoke(Show_Sys, new object[] { "Tcp Listener Thread Start!" });
- try
- {
- Int32 port = Convert.ToInt32(Str_LinstenPort.Text);
- IPAddress localAddr = IPAddress.Parse(LocalIP.Text);
- server = new TcpListener(localAddr, port);
- server.Start();
- Byte[] bytes = new Byte[256];
- String data = null;
- // 进入监听循环
- while (IsGoOn)
- {
- this.Invoke(Show_Sys, new object[] { "Waiting for a connection... " });
- TcpClient client = server.AcceptTcpClient();
- this.Invoke(Show_Sys, new object[] { "Connected!" });
- data = null;
- NetworkStream stream = client.GetStream();
- int i;
- while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
- {
- data = System.Text.Encoding.Unicode.GetString(bytes, 0, i);
- this.Invoke(Show_Sys, new object[] { "Received: " + data });
- this.Invoke(Show_Rec, new object[] { data });
- }
- client.Close();
- //记录进度
- this.Invoke(Show_Stp, new object[] { 1 });
- Thread.Sleep(100);
- }
- }
- catch (SocketException ex)
- {
- this.Invoke(Show_Sys, new object[] { "SocketException: " + ex.Message });
- }
- finally
- {
- //退出server
- server.Stop();
- this.Invoke(Show_Sys, new object[] { "Tcp Listener Thread End!" });
- }
- }
- catch
- {
- ;
- }
- }
- /// <summary>
- /// 在关闭窗口时结束线程
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- IsGoOn=false;
- if(server!=null)
- {
- server.Stop();
- }
- }
- private void 开始监听ToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Thread UDP_lis_th = new Thread(new ThreadStart(this.UDP_Listener));
- UDP_lis_th.Start();
- toolStripProgressBar1.Value = 10;
- toolStripProgressBar2.Value = 10;
- //锁定参数窗口
- Str_LinstenPort.Enabled = false;
- Str_SendPort.Enabled = false;
- Str_TargetIP.Enabled = false;
- UserName.Enabled = false;
- LocalIP.Enabled = false;
- }
- private void 结束监听ToolStripMenuItem_Click(object sender, EventArgs e)
- {
- IsGoOn = false;
- if (server != null)
- {
- server.Stop();
- }
- WriteSysMsg("Tcp Listener Thread End!");
- toolStripProgressBar1.Value = 10;
- toolStripProgressBar2.Value = 10;
- Str_LinstenPort.Enabled = true;
- Str_SendPort.Enabled = true;
- Str_TargetIP.Enabled = true;
- UserName.Enabled = true;
- LocalIP.Enabled = true;
- }
- private void buttonExit_Click(object sender, EventArgs e)
- {
- IsGoOn = false;
- if (server != null)
- {
- server.Stop();
- }
- Close();
- }
- }
- }
复制代码
如何使用:
[attach]48517[/attach]
填好相应的内容后,请点击“开始监听”
附件为编译后的程序,运行需安装.NET framwork。
本文内容由 Rainyboy 提供
[attach]48518[/attach]
[attach]48520[/attach] |