.Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务3[聊天室]
本案例使用前面封装的网络服务类编写简易聊天室,采用Tcp和多线程相关技术:
App.config文件:
示范代码<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!--本地服务器名--> <add key="ServerName" value="127.0.0.1"/> <!--本地端口--> <add key="ServerPort" value="6000"/> <!--远程服务器名--> <add key="RemoteServerName" value="127.0.0.1"/> <!--远程服务器端口--> <add key="RemoteServerPort" value="6000"/> </appSettings> </configuration>
窗体内所有代码:
示范代码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 TcpLabCommon; using System.Net.Sockets; using System.Net; using System.Configuration; using System.Threading; using System.IO; namespace TcpLabChat1 { public partial class FrmChat : Form { delegate void UpdateViewHandler(NetPacket packet); delegate void UpdateViewWithMsgHandler(string msg); /// <summary> /// Tcp服务对象[提供发包和收包功能],接收消息和文件使用 /// </summary> NetPacketService tcpPacketServiceSvr = null; /// <summary> /// Tcp服务对象[提供发包和收包功能],发送消息和文件使用 /// </summary> NetPacketService tcpPacketServiceClient = null; /// <summary> /// 客户端Socket[发送消息和文件] /// </summary> Socket clientSocket = null; public string ServerName { get { return ConfigurationManager.AppSettings["ServerName"]; } } public Int32 ServerPort { get { return Convert.ToInt32(ConfigurationManager.AppSettings["ServerPort"]); } } public String RemoteServerName { get { return ConfigurationManager.AppSettings["RemoteServerName"]; } } public Int32 RemoteServerPort { get { return Convert.ToInt32(ConfigurationManager.AppSettings["RemoteServerPort"]); } } public FrmChat() { InitializeComponent(); } private void FrmChat_Load(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart(ReceiveMessage)); thread.IsBackground = true;//设置当前线程为后台线程,以使当主窗体被关闭后自动结束线程 thread.Start(); } private void ReceiveMessage() { Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); EndPoint endPoint = new IPEndPoint(IPAddress.Parse(ServerName), ServerPort);//创建一个终结点 serverSocket.Bind(endPoint);//绑定终结点 serverSocket.Listen(0);//开始监听 Socket ctSocket = serverSocket.Accept();//接收一个请求 NetworkStream netStream = new NetworkStream(ctSocket); tcpPacketServiceSvr = new NetPacketTcpService(netStream); while(true) { //在窗口界面所在的线程运行委托指向的方法,避免跨线程访问UI问题 Invoke(new UpdateViewHandler(UpdateView), tcpPacketServiceSvr.ReceivePacket()); } } /// <summary> /// 更新界面 /// </summary> /// <param name="packet"></param> private void UpdateView(NetPacket packet) { String msglist = txtMsgList.Text; switch (packet.PacketHead.PType) { case PacketType.STRING: msglist += "\r\n对方说:"+packet.Data.ToString(); break; case PacketType.BINARY: NetFile f = tcpPacketServiceSvr.ParseFile((Byte[])packet.Data); msglist += "\r\n接收了对方发送的文件:"+f.FileName; FileStream fs = null; try { string fname = Application.StartupPath+"\\"+f.FileName; fs = new FileStream(fname, FileMode.Create); fs.Write(f.Content, 0, f.Content.Length); fs.Flush(); } catch (Exception e) { MessageBox.Show(e.Message); } finally { fs.Close(); } break; case PacketType.COMPLEX: break; default: break; } txtMsgList.Text = msglist; } private void UpdateView(string msg) { String msglist = txtMsgList.Text; msglist += "\r\n"+msg; txtMsgList.Text = msglist; } /// <summary> /// 发送消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendMsg_Click(object sender, EventArgs e) { if (txtMsg.Text.Trim().Length == 0) return; if (clientSocket == null) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect(IPAddress.Parse(RemoteServerName), RemoteServerPort); NetworkStream netStream = new NetworkStream(clientSocket); tcpPacketServiceClient = new NetPacketTcpService(netStream); } tcpPacketServiceClient.SendText(txtMsg.Text.Trim()); String msglist = txtMsgList.Text; msglist += "\r\n我说:" + txtMsg.Text.Trim(); txtMsgList.Text = msglist; } /// <summary> /// 发送文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendFile_Click(object sender, EventArgs e) { OpenFileDialog fd = new OpenFileDialog(); if (fd.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) { return; } if (clientSocket == null) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect(IPAddress.Parse(RemoteServerName), RemoteServerPort); NetworkStream netStream = new NetworkStream(clientSocket); tcpPacketServiceClient = new NetPacketTcpService(netStream); } //在新的线程中完成文件发送 Thread thread = new Thread(delegate() //采用C#2.0匿名方法语法 { tcpPacketServiceClient.SendFile(fd.FileName); //在窗口界面所在的线程运行委托指向的方法,避免跨线程访问UI问题 Invoke(new UpdateViewWithMsgHandler(UpdateView), "我发送了文件:" + new FileInfo(fd.FileName).Name); }); thread.IsBackground = true; thread.Start(); } } }
使用方式:请将编译后的debug目录拷贝两份,分别配置不同的端口即可,比如a目录的配置端口为本地6001,远程6002,b目录的配置端口为本地6002,远程6001,这样即可在同一台机器实现通信。
posted on 2012-03-28 09:51 jiangtongcn 阅读(355) 评论(0) 编辑 收藏 举报