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:"+ \t\t\t\t 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;這行代碼,不然子線程無法操作主界面的控件。


分享到:


相關文章: