1. 首页
  2. >
  3. 编程技术
  4. >
  5. C#

C#实现Socket多人聊天-无服务器 直联版

前面有一篇文章写了关于Socket的一些理解,今天小编就用C#来实现以下某聊天软件的多人聊天系统(别问我为啥不用C++,只是因为C#效率高,一个字爽啊)。

我们先来看一下整体的思路:

C#实现Socket多人聊天-无服务器 直联版

整体思路是利用线程池达到接收多个聊天请求。先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时请求端与接收端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据

前端页面很简单,一个显示框一个输入框:

C#实现Socket多人聊天-无服务器 直联版

具体代码实现:

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 System.Net.Sockets;
using System.Net;
using System.Threading;
namespace WindowsFormsApplication2
{
 public partial class Form1 : Form
 {
 public delegate void CallBack(string str);
 public Socket socListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 public Form1()
 {
 InitializeComponent();
 CheckForIllegalCrossThreadCalls = false;
 }
 private void Form1_Load(object sender, EventArgs e)
 {
 string ip_server = string.Empty;
 //获取主机名
 string name = Dns.GetHostName();
 //通过主机名获取本地IP(包含所有IP,有几个网卡就有几个IP,IP分IPV4和IPV6,这里要注意我们用IPV4)
 IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
 
 foreach (IPAddress ipa in ipadrlist)
 {
 //筛选出我们要的IP,这里因为我是多个网卡,所以我需要这样筛选,大家可以用自己的特征去筛选 IP我打码了
 if (ipa.ToString().Contains("!!!!!!")) ip_server = ipa.ToString();
 }
 //小编自己用,大家可以不理会
 ip_server = ipadrlist[3].ToString(); 
 //注意,你要用的端口,这个端口要确保没有被占用
 int port = 6000;
 IPAddress address = IPAddress.Parse(ip_server);
 //创建网络端口,包括ip和端口
 IPEndPoint endPoint = new IPEndPoint(address, port);
 // 绑定套接字
 socListen.Bind(endPoint);
 socListen.Listen(5);
 //创建线程,开始接受请求,因为Accept方法会阻塞,所以要用多线程
 Thread thread = new Thread(acceptConnect);
 thread.Start();
 }
 private void button1_Click(object sender, EventArgs e)
 {
 //为简单起见,限制聊天消息在1024个字节
 string msg = richTextBox2.Text.Trim();
 if (msg.Length > 1024)
 {
 MessageBox.Show("the message is too long");
 return;
 }
 byte[] btMsg = Encoding.UTF8.GetBytes(msg);
 byte[] buffer = new byte[1024];
 if (!socListen.Connected)
 {
 try
 {
 //对方IP
 IPAddress address_Server = IPAddress.Parse("!!!!!!");
 //除了对方IP 你还得知道对方的程序跑在什么端口
 IPEndPoint endPoint_Server = new IPEndPoint(address_Server, 6000);
 //连接对方
 socListen.Connect(endPoint_Server);
 }
 catch (Exception ex)
 {
 MessageBox.Show(ex.Message);
 }
 }
 //发送消息
 int len = socListen.Send(btMsg, btMsg.Length, SocketFlags.None);
 richTextBox2.Clear();
 }
 public void acceptConnect()
 {
 while (true)
 {
 Socket client = null;
 client = socListen.Accept();
 //利用线程池循环接收多个请求
 ThreadPool.QueueUserWorkItem(new WaitCallback(receiveMsg),client);
 }
 }
 //接收聊天消息
 public void receiveMsg(object clientObj)
 {
 Socket client = clientObj as Socket;
 while (true)
 {
 byte[] bt = new byte[1024];
 try
 {
 client.Receive(bt, bt.Length, SocketFlags.None);
 string msg = Encoding.UTF8.GetString(bt); 
 string clientEndPoint = client.RemoteEndPoint.ToString();
 listBox1.Items.Add("from Clinet point:"+ 				 clientEndPoint.Substring(clientEndPoint.IndexOf(":")+1,clientEndPoint.Length-clientEndPoint.IndexOf(":")-1));
 listBox1.Items.Add("\t" + msg);
 }
 catch (Exception ex)
 {
 client.Close();
 }
 }
 }
 }
}

地址运行效果如下:

C#实现Socket多人聊天-无服务器 直联版

注:

1、这里面还有很多细节小编没有去处理,核心功能是实现了的。但这并不是一个OK的工程,如果有这方面的需要的朋友,需要自己去处理细节问题。

2、 需要在Form1的构造函数内加上CheckForIllegalCrossThreadCalls = false;这行代码,不然子线程无法操作主界面的控件。