201803041447->初试c#socket聊天室
2018-03-04 15:10
399 查看
目的:利用socket来完成简单多人聊天室
服务端
Program.cs
namespace chatserver
{
internal class Program
{
private static void Main(string[] args)
{
Server server = new Server("127.0.0.1", 9404);
server.Start();
}
}
}
Client.cs
internal class Client
{
private Server mServer;
private Socket ClientSocket;
private bool mClientState;
private static readonly byte[] ReciveBuffer = new byte[512];//缓冲区
internal Client(Server server, Socket clientsocket)
{
this.mServer = server;
this.ClientSocket = clientsocket;
StartReciveSocketData();
}
private void StartReciveSocketData()
{
mClientState = true;
Thread thread = new Thread(ReciveMessage);
thread.IsBackground = true;
thread.Start();
}
private void ReciveMessage()
{
int length = -1;
while (mClientState)
{
if (this.ClientSocket.Poll(10, SelectMode.SelectRead))//处理客户端断线
{
Recycle();
Console.WriteLine("client connect fail...");
break;
}
try
{
length = this.ClientSocket.Receive(ReciveBuffer);
string message = Encoding.UTF8.GetString(ReciveBuffer, 0, length);
SendMessage(message);
}
catch (Exception ex)
{
Console.WriteLine(">error : " + ex.ToString());
}
}
}
private void SendMessage(string message)//广播消息
{
if (!string.IsNullOrEmpty(message))
{
this.mServer.DispatchMessage(message);
}
}
internal void RealSendMessage(string message)//发送消息
{
if (!string.IsNullOrEmpty(message))
{
message = this.ClientSocket.GetHashCode() + " > " + message;
byte[] bytes = Encoding.UTF8.GetBytes(message);
this.ClientSocket.Send(bytes);
Console.WriteLine(string.Format(">send {0} message > {1} ", this.ClientSocket.GetHashCode(), message));
}
}
internal void Recycle()//回收
{
mClientState = false;
ClientSocket.Dispose();
ClientSocket.Close();
}
internal bool IsConnected()//判断是否未断线
{
return ClientSocket.Connected;
}
}
Server.cs
internal class Server
{
protected IPEndPoint mIPEndPoint;
private Socket mServerSocket;//主线程套接字
private bool mServerState = false;//服务器状态
protected static List<Client> mClients = new List<Client>();//所有用户
private static readonly object chatlock = new object();//避免多线程下数据多发
public Server(string adress, int port)
{
IPAddress iPAddress = IPAddress.Parse(adress);
this.mIPEndPoint = new IPEndPoint(iPAddress, port);
}
public Server(int port)
{
this.mIPEndPoint = new IPEndPoint(IPAddress.Any, port);
}
public void Start()
{
mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//新建套接字
if (this.mIPEndPoint == null)
{
Console.WriteLine(">mIPEndPoint nullable...");
return;
}
mServerSocket.Bind(this.mIPEndPoint);//绑定端点
Console.WriteLine(">Server start...");
mServerState = true;
mServerSocket.Listen(10);//开始侦听
while (mServerState)//死循环,每收到一个用户就专门用一个套接字对象去与用户作沟流
{
try
{
Socket clientsocket = mServerSocket.Accept();//accept会阻塞线程,如果没有客户端传入,程序会一直处于假死状态,切记,这里accept只用于学习socket
Client client = new Client(this, clientsocket);//将套接字对像传入用户
mClients.Add(client);
}
catch (Exception)
{
Recycle();
}
}
}
public void Recycle()//回收
{
mServerSocket.Close();
mServerState = false;
if (mClients != null && mClients.Any())
{
mClients.ForEach(p => p.Recycle());
mClients.Clear();
}
Console.WriteLine("server closed...");
}
internal void DispatchMessage(string message)//广播消息并处理已经断线的用户
{
lock (chatlock)
{
var AllDisConnectedClients = new List<Client>();
mClients.ForEach(p =>
{
if (p.IsConnected())
{
p.RealSendMessage(message);
}
else
{
//AllDisConnectedClients.Add(p);
}
});
if (AllDisConnectedClients != null && AllDisConnectedClients.Any())
{
AllDisConnectedClients.ForEach(p =>
{
p.Recycle();
});
}
}
}
}
客户端,需要自己关联组件
ChatManager.cs
public class ChatManager : MonoBehaviour
{
private string Message;
private Thread mThread;
4000
private Socket mSocket;
[SerializeField]
private Text mText = null;
[SerializeField]
private InputField mInputField = null;//输入栏
[SerializeField]
private Button mButton = null;
private static readonly byte[] buffer = new byte[512];
// Use this for initialization
private void Awake()
{
Application.runInBackground = true;
}
private void Start()
{
Thread thread = new Thread(InitializationSocket);
thread.IsBackground = true;
thread.Start();
mButton.onClick.AddListener(OnClick);
mText.text = string.Empty;
}
private void InitializationSocket()
{
IPAddress address = IPAddress.Parse("127.0.0.1");
IPEndPoint iPEndPoint = new IPEndPoint(address, 9404);
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
mSocket.Connect(iPEndPoint);
}
catch (Exception ex)
{
Debug.Log(">error : " + ex.ToString());
}
mThread = new Thread(ReciveMessage);
mThread.Start();
}
private void ReciveMessage()
{
while (true)
{
if (mSocket.Connected == false)
{
break;
}
int length = mSocket.Receive(buffer);
if (length > 0)
{
//lock (Message)//开锁则不能显示信息原因--主线程一直监控message变量,子线程不能调用
{
Message = Encoding.UTF8.GetString(buffer, 0, length);
Debug.Log("recive message : " + Message);
}
}
}
}
private void OnClick()
{
if (mInputField.text != null && mInputField.text != "")
{
SendChatMessage(mInputField.text);
mInputField.text = string.Empty;
}
}
private void SendChatMessage(string text)
{
Byte[] texts = Encoding.UTF8.GetBytes(text);
mSocket.Send(texts);
}
// Update is called once per frame
private void Update()
{
if (Input.GetKeyDown(KeyCode.J))
{
Debug.Log("this.mThread.IsAlive : " + this.mThread.IsAlive);
Debug.Log("this.mSocket.Connected : " + this.mSocket.Connected);
}
if (Message != null && !string.IsNullOrEmpty(Message))
{
mText.text += (Message + "\n");
Message = string.Empty;
}
}
private void OnDestroy()
{
this.mThread.Abort();
this.mSocket.Shutdown(SocketShutdown.Both);
this.mSocket.Close();
}
}
服务端
Program.cs
namespace chatserver
{
internal class Program
{
private static void Main(string[] args)
{
Server server = new Server("127.0.0.1", 9404);
server.Start();
}
}
}
Client.cs
internal class Client
{
private Server mServer;
private Socket ClientSocket;
private bool mClientState;
private static readonly byte[] ReciveBuffer = new byte[512];//缓冲区
internal Client(Server server, Socket clientsocket)
{
this.mServer = server;
this.ClientSocket = clientsocket;
StartReciveSocketData();
}
private void StartReciveSocketData()
{
mClientState = true;
Thread thread = new Thread(ReciveMessage);
thread.IsBackground = true;
thread.Start();
}
private void ReciveMessage()
{
int length = -1;
while (mClientState)
{
if (this.ClientSocket.Poll(10, SelectMode.SelectRead))//处理客户端断线
{
Recycle();
Console.WriteLine("client connect fail...");
break;
}
try
{
length = this.ClientSocket.Receive(ReciveBuffer);
string message = Encoding.UTF8.GetString(ReciveBuffer, 0, length);
SendMessage(message);
}
catch (Exception ex)
{
Console.WriteLine(">error : " + ex.ToString());
}
}
}
private void SendMessage(string message)//广播消息
{
if (!string.IsNullOrEmpty(message))
{
this.mServer.DispatchMessage(message);
}
}
internal void RealSendMessage(string message)//发送消息
{
if (!string.IsNullOrEmpty(message))
{
message = this.ClientSocket.GetHashCode() + " > " + message;
byte[] bytes = Encoding.UTF8.GetBytes(message);
this.ClientSocket.Send(bytes);
Console.WriteLine(string.Format(">send {0} message > {1} ", this.ClientSocket.GetHashCode(), message));
}
}
internal void Recycle()//回收
{
mClientState = false;
ClientSocket.Dispose();
ClientSocket.Close();
}
internal bool IsConnected()//判断是否未断线
{
return ClientSocket.Connected;
}
}
Server.cs
internal class Server
{
protected IPEndPoint mIPEndPoint;
private Socket mServerSocket;//主线程套接字
private bool mServerState = false;//服务器状态
protected static List<Client> mClients = new List<Client>();//所有用户
private static readonly object chatlock = new object();//避免多线程下数据多发
public Server(string adress, int port)
{
IPAddress iPAddress = IPAddress.Parse(adress);
this.mIPEndPoint = new IPEndPoint(iPAddress, port);
}
public Server(int port)
{
this.mIPEndPoint = new IPEndPoint(IPAddress.Any, port);
}
public void Start()
{
mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//新建套接字
if (this.mIPEndPoint == null)
{
Console.WriteLine(">mIPEndPoint nullable...");
return;
}
mServerSocket.Bind(this.mIPEndPoint);//绑定端点
Console.WriteLine(">Server start...");
mServerState = true;
mServerSocket.Listen(10);//开始侦听
while (mServerState)//死循环,每收到一个用户就专门用一个套接字对象去与用户作沟流
{
try
{
Socket clientsocket = mServerSocket.Accept();//accept会阻塞线程,如果没有客户端传入,程序会一直处于假死状态,切记,这里accept只用于学习socket
Client client = new Client(this, clientsocket);//将套接字对像传入用户
mClients.Add(client);
}
catch (Exception)
{
Recycle();
}
}
}
public void Recycle()//回收
{
mServerSocket.Close();
mServerState = false;
if (mClients != null && mClients.Any())
{
mClients.ForEach(p => p.Recycle());
mClients.Clear();
}
Console.WriteLine("server closed...");
}
internal void DispatchMessage(string message)//广播消息并处理已经断线的用户
{
lock (chatlock)
{
var AllDisConnectedClients = new List<Client>();
mClients.ForEach(p =>
{
if (p.IsConnected())
{
p.RealSendMessage(message);
}
else
{
//AllDisConnectedClients.Add(p);
}
});
if (AllDisConnectedClients != null && AllDisConnectedClients.Any())
{
AllDisConnectedClients.ForEach(p =>
{
p.Recycle();
});
}
}
}
}
客户端,需要自己关联组件
ChatManager.cs
public class ChatManager : MonoBehaviour
{
private string Message;
private Thread mThread;
4000
private Socket mSocket;
[SerializeField]
private Text mText = null;
[SerializeField]
private InputField mInputField = null;//输入栏
[SerializeField]
private Button mButton = null;
private static readonly byte[] buffer = new byte[512];
// Use this for initialization
private void Awake()
{
Application.runInBackground = true;
}
private void Start()
{
Thread thread = new Thread(InitializationSocket);
thread.IsBackground = true;
thread.Start();
mButton.onClick.AddListener(OnClick);
mText.text = string.Empty;
}
private void InitializationSocket()
{
IPAddress address = IPAddress.Parse("127.0.0.1");
IPEndPoint iPEndPoint = new IPEndPoint(address, 9404);
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
mSocket.Connect(iPEndPoint);
}
catch (Exception ex)
{
Debug.Log(">error : " + ex.ToString());
}
mThread = new Thread(ReciveMessage);
mThread.Start();
}
private void ReciveMessage()
{
while (true)
{
if (mSocket.Connected == false)
{
break;
}
int length = mSocket.Receive(buffer);
if (length > 0)
{
//lock (Message)//开锁则不能显示信息原因--主线程一直监控message变量,子线程不能调用
{
Message = Encoding.UTF8.GetString(buffer, 0, length);
Debug.Log("recive message : " + Message);
}
}
}
}
private void OnClick()
{
if (mInputField.text != null && mInputField.text != "")
{
SendChatMessage(mInputField.text);
mInputField.text = string.Empty;
}
}
private void SendChatMessage(string text)
{
Byte[] texts = Encoding.UTF8.GetBytes(text);
mSocket.Send(texts);
}
// Update is called once per frame
private void Update()
{
if (Input.GetKeyDown(KeyCode.J))
{
Debug.Log("this.mThread.IsAlive : " + this.mThread.IsAlive);
Debug.Log("this.mSocket.Connected : " + this.mSocket.Connected);
}
if (Message != null && !string.IsNullOrEmpty(Message))
{
mText.text += (Message + "\n");
Message = string.Empty;
}
}
private void OnDestroy()
{
this.mThread.Abort();
this.mSocket.Shutdown(SocketShutdown.Both);
this.mSocket.Close();
}
}
相关文章推荐
- 以C#编写的Socket服务器的Android手机聊天室Demo
- 终于搞定了一个C#的聊天室 使用的SQLServer+VS 用的Socket 整理下搜的书签
- C#基于Socket的简单聊天室实践
- C# 异步TCP Socket聊天室(1服务器,N客户端)
- C#基于Socket的简单聊天室实践
- Flex和java的socket通信(五)聊天室的补充-在线列表-私聊<转>
- 以C#编写的Socket服务器的Android手机聊天室Demo
- C# socket编程实践——简单聊天室
- Flex 与 c# socket 完整实例:聊天室
- C# Socket 异步 聊天室
- C# 异步TCP Socket聊天室(1服务器,N客户端)
- C# 异步TCP Socket聊天室(1服务器,N客户端)
- C#基于Socket的简单聊天室实践
- C#Socket 聊天室
- C# 异步TCP Socket聊天室(1服务器,N客户端)
- C# Socket 同步 多线程 聊天室
- C#实现Socket聊天室
- [学习笔记]C# Socket初试-服务端
- C# 聊天室基于.Net4 Socket 协议开发
- C#的Socket编程基础——Unity的简单聊天室