局域网之间的通讯实现
2013-12-24 22:08
411 查看
局域网之间通讯有很多种方法,比如可以用数据库存储的方式实现,还可以用udp来实现,这里是用tcp来实现的,用tcp来通讯的话可以说是有点麻烦的,因为要保持各个用户与服务器之间的连接,连接一断便不能通讯了,所以个人觉得这个地方比较麻烦;
要实现Socket通讯的话首先可以把它分成两个项目来区别,一个是服务器项目(Server),一个是客户端项目(Client)。
服务器项目的实现可以大致的分成 部分,1:创建一个总连接点,这个连接点负责与客户端的连接,我们不能把连接和通讯都引用到一个连接上,这样服务器会崩溃的,而每个用户都是独立的,所以我们要利用线程来创建一个新的通讯实例,这个连接和通讯各个用户之间都是互不干扰的了,还有一个要注意的就是跨线程调用控件的话是不行的,所以我们又要利用委托存放要调用的功能在用this.Invoke()的方法来跨线程引用控件,接下来就是具体实现响应通讯了;
客户端相对来说要更容易些,创建一个客户端连接实例,与远程服务器连接起来,然后就是大致的通讯实现功能了。
下面是我个人的实现代码和实现的心得,附加了大致的注释,实现了群聊,私聊等功能。
通讯类(Communication)
View Code
要实现Socket通讯的话首先可以把它分成两个项目来区别,一个是服务器项目(Server),一个是客户端项目(Client)。
服务器项目的实现可以大致的分成 部分,1:创建一个总连接点,这个连接点负责与客户端的连接,我们不能把连接和通讯都引用到一个连接上,这样服务器会崩溃的,而每个用户都是独立的,所以我们要利用线程来创建一个新的通讯实例,这个连接和通讯各个用户之间都是互不干扰的了,还有一个要注意的就是跨线程调用控件的话是不行的,所以我们又要利用委托存放要调用的功能在用this.Invoke()的方法来跨线程引用控件,接下来就是具体实现响应通讯了;
客户端相对来说要更容易些,创建一个客户端连接实例,与远程服务器连接起来,然后就是大致的通讯实现功能了。
下面是我个人的实现代码和实现的心得,附加了大致的注释,实现了群聊,私聊等功能。
通讯类(Communication)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Server; namespace Client { public partial class forClient : Form { public forClient() { InitializeComponent(); } private delegate void ListDelegate(Communication comm); private ListDelegate listInfo = null;//用于绑定成员 private delegate void MessageDelegate(Communication comm); private MessageDelegate MessageInfo = null;//用于添加聊天消息 private delegate void ClearDelegate(); private ClearDelegate ClearInfo = null;//用于清除成员列表 private delegate void EndDelegate(Communication commun); private EndDelegate EndInfo = null; Socket client = null; EndPoint endPoint = null; private void 开启服务ToolStripMenuItem_Click(object sender, EventArgs e) { int port = 0; client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (!int.TryParse(txtPort.Text, out port)) port = 8080; endPoint = new IPEndPoint(IPAddress.Parse(txtIP.Text), port); client.Connect(endPoint); rtbMessage.Text = "连接服务器成功!"; Thread t = new Thread(ReceiveInfo); t.Start(client); } public void ClearList() //清除成员列表 { this.lvInfo.Clear(); } public void EndClient(Communication commun) //移除成员列表里离线的成员 { foreach (ListViewItem items in lvInfo.Items) { //如果成员列表上有此用户,则移除 if (items.SubItems[0].Text.Equals(commun.Name)) { items.Remove(); break; } } } public void ReceiveInfo(object c)//接收服务器的信息 { byte[] b = new byte[1024]; Socket client = c as Socket; ClearInfo = new ClearDelegate(ClearList); while(true) { try { client.Receive(b); } catch (Exception) { client.Dispose(); return; } Communication comm = DeserializeObject(b) as Communication; if (comm.Types == 2)//服务器回发过来的信息 { listInfo = new ListDelegate(BindListView); this.Invoke(listInfo, comm); } else if (comm.Types == 1 || comm.Types == 3) { MessageInfo = new MessageDelegate(AddMessage); this.Invoke(MessageInfo, comm); } else //下线执行 { MessageInfo = new MessageDelegate(AddMessage); this.Invoke(MessageInfo, comm); EndInfo = new EndDelegate(EndClient); this.Invoke(EndInfo,comm); } } } public void BindListView(Communication comm) //绑定客户端人物信息到ListView控件上 { if(comm.IsFistLogin) { lvInfo.Items.Clear();//第一次添加的时候(判定为true时)清除原有的旧成员 } ListViewItem items = new ListViewItem(comm.Name); items.SubItems.Add(comm.Ip); items.SubItems.Add(comm.Port); lvInfo.Items.Add(items); } public void AddMessage(Communication comm)//添加聊天消息 { rtbMessage.Text += "\n"+comm.Name + ":" + comm.Message; } public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象 { object newOjb = null; if (pBytes == null) return newOjb; MemoryStream memory = new MemoryStream(pBytes); memory.Position = 0; BinaryFormatter formatter = new BinaryFormatter(); newOjb = formatter.Deserialize(memory); memory.Close(); return newOjb; } public byte[] SerializeObject(object pObj)//序列化对象为二进制的数 { if (pObj == null) return null; MemoryStream memory = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(memory, pObj); memory.Position = 0; byte[] read = new byte[memory.Length]; memory.Read(read, 0, read.Length); memory.Close(); return read; } private void btnSend_Click(object sender, EventArgs e) { Communication comm = new Communication() { Name = Dns.GetHostName(), Message = txtMessage.Text, Types = 1 }; if (lvInfo.SelectedItems.Count > 0)//私聊 { comm.Types = 3; string ePoint = lvInfo.SelectedItems[0].SubItems[1].Text +":"+ lvInfo.SelectedItems[0].SubItems[2].Text; comm.ToEndPoint = ePoint; } byte[] b = SerializeObject(comm); client.Send(b); lvInfo.SelectedItems.Clear();//清除选中的个数 } private void 退出程序ToolStripMenuItem_Click(object sender, EventArgs e) { Communication comm = new Communication() { Name = Dns.GetHostName(), Message = "下线了!", Types = 4//用户下线类型 }; byte[] b = SerializeObject(comm); client.Send(b); client.Dispose(); Application.Exit(); } private void forClient_Load(object sender, EventArgs e) { //127.0.0.1 用于获取本机IP txtIP.Text = "192.168.1.100"; txtPort.Text = "8080"; } } }
View Code
相关文章推荐
- oc下实现局域网udp广播通讯使用开源框架GCDAsyncUdpSocket
- VirtualBox实现宿主机和虚拟机之间网络的通讯
- UDP网间通讯(不同局域网之间通讯) UDP打洞详细过程 图文
- AIDL实现不同应用之间跨进程通讯及传递与返回各种数据类型和远程接口回调
- Prism 框架中使用IEventAggregator事件聚合器简单实现ViewModel之间的通讯
- 代理实现两个窗口之间的通讯
- 局域网内主机之间Socket通信实现
- Android开发之实现两个手机之间的通讯
- 用Visual C#实现局域网点对点通讯
- 线程开发之多线程之间的通讯实现
- .NET与JSP页面之间消息通讯(跨域,使用html5的postMessage实现)
- C#.NET通过Socket实现平行主机之间网络通讯(含图片传输的Demo演示)
- 代理实现两个窗口之间的通讯
- 利用OTP.NET框架来实现C#与Erlang Node之间的通讯
- 如何建立一个小型的局域网,来实现电脑与电脑之间的通信
- 用C#实现局域网点对点通讯
- 【Java多线程】多线程之间实现通讯与生产者与消费者模式
- 用Visual C#实现局域网点对点通讯
- 用Visual C#实现局域网点对点通讯
- WebSocket实现Android客户端之间的简单通讯