2012年3月28日星期三

.Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]

.Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]



本案例使用前面封装的网络服务类编写简易聊天室,采用Tcp和异步套接字相关技术:

image

App.config文件:

示范代码<??><configuration>    <appSettings>        <!--本地服务器名-->        <add key="ServerName" value="127.0.0.1"/>        <!--本地端口-->        <add key="ServerPort" value="6001"/>        <!--远程服务器名-->        <add key="RemoteServerName" value="127.0.0.1"/>        <!--远程服务器端口-->        <add key="RemoteServerPort" value="6002"/>    </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>        /// 文件对话框        /// </summary>        OpenFileDialog fd = new OpenFileDialog();        /// <summary>        /// Tcp服务对象[提供发包和收包功能],接收消息和文件使用        /// </summary>        NetPacketService tcpPacketServiceSvr = null;        /// <summary>        /// Tcp服务对象[提供发包和收包功能],发送消息和文件使用        /// </summary>        NetPacketService tcpPacketServiceClient = null;                       /// <summary>        /// 客户端Socket[发送消息和文件]        /// </summary>        Socket clientSocket = null;        /// <summary>        /// 本地服务器名        /// </summary>        public string ServerName        {            get            {                return ConfigurationManager.AppSettings["ServerName"];            }        }        /// <summary>        /// 本地监听端口        /// </summary>        public Int32 ServerPort        {            get            {                return Convert.ToInt32(ConfigurationManager.AppSettings["ServerPort"]);            }        }        /// <summary>        /// 对方服务器名        /// </summary>        public String RemoteServerName        {            get            {                return ConfigurationManager.AppSettings["RemoteServerName"];            }        }        /// <summary>        /// 对方服务器监听端口        /// </summary>        public Int32 RemoteServerPort        {            get            {                return Convert.ToInt32(ConfigurationManager.AppSettings["RemoteServerPort"]);            }        }        public FrmChat()        {            InitializeComponent();        }        private void FrmChat_Load(object sender, EventArgs e)        {            ReceiveMessage();        }        /// <summary>        /// 异步接收对方发来的消息        /// </summary>        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);//开始监听            serverSocket.BeginAccept(new AsyncCallback(AsyncCallbackAccept),serverSocket);//接收一个请求                   }        private void AsyncCallbackAccept(IAsyncResult result)        {            Socket serverSocket = (Socket)result.AsyncState;            Socket ctSocket = serverSocket.EndAccept(result);            NetworkStream netStream = new NetworkStream(ctSocket);            tcpPacketServiceSvr = new NetPacketTcpAsynService(netStream);            (tcpPacketServiceSvr as NetPacketTcpAsynService).OnReceivedPacket += new TcpAsynHandler1(FrmChat_OnReceivedPacket);                                   tcpPacketServiceSvr.ReceivePacket();                                    }        void FrmChat_OnReceivedPacket(NetPacket packet)        {            //在窗口界面所在的线程运行委托指向的方法,避免跨线程访问UI问题            Invoke(new UpdateViewHandler(UpdateView), packet);        }        /// <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 NetPacketTcpAsynService(netStream);            }            //注册事件,当发送成功后执行的函数[注意该事件只注册一次]            //取消订阅事件            (tcpPacketServiceClient as NetPacketTcpAsynService).OnAfterSendPacket -= new TcpAsynHandler2(FrmChat_OnAfterSendPacket);            //再次订阅事件            (tcpPacketServiceClient as NetPacketTcpAsynService).OnAfterSendPacket += new TcpAsynHandler2(FrmChat_OnAfterSendPacket);            //发包            tcpPacketServiceClient.SendText(txtMsg.Text.Trim());                    }        /// <summary>        /// 当发送成功后执行的函数        /// </summary>        /// <param name="msg"></param>        void FrmChat_OnAfterSendPacket(NetPacketHead packetHead)        {            switch (packetHead.PType)            {                case PacketType.STRING:                    String msglist = txtMsgList.Text;                    msglist += "\r\n我说:" + txtMsg.Text.Trim();                    txtMsgList.Text = msglist;                    break;                case PacketType.BINARY:                    //在窗口界面所在的线程运行委托指向的方法,避免跨线程访问UI问题                                    Invoke(new UpdateViewWithMsgHandler(UpdateView), "我发送了文件:" + new FileInfo(fd.FileName).Name);                    break;                case PacketType.COMPLEX:                    break;                default:                    break;            }                    }        /// <summary>        /// 发送文件        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void btnSendFile_Click(object sender, EventArgs e)        {                        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 NetPacketTcpAsynService(netStream);            }            //注册事件,当发送成功后执行的函数[注意该事件只注册一次]            //取消订阅事件            (tcpPacketServiceClient as NetPacketTcpAsynService).OnAfterSendPacket -= new TcpAsynHandler2(FrmChat_OnAfterSendPacket);            //再次订阅事件            (tcpPacketServiceClient as NetPacketTcpAsynService).OnAfterSendPacket += new TcpAsynHandler2(FrmChat_OnAfterSendPacket);                                    tcpPacketServiceClient.SendFile(fd.FileName);                                }    }}


TAG:C# Tcp Udp 粘包