赞
踩
比起使用异步程序,同步程序更简单明了,而且不会引发线程问题。只需要在阻塞方法前机上一层判断,有数据可读才调用Receive,有数据可写才调用Send,既能实现功能,又不会卡住程序,于是给Socket提供了Poll方法。Poll方法将检查Socket的状态,如果不想让方法阻塞,将等待参数设置为0即可。
使用Poll方法写的服务器端程序,而客户端使用上一篇的程序。
class ClientState
{
public Socket socket;
public byte[] recvBuffer = new byte[1024];
public string recvStr = "";
}
主循环结构while(true){ },不断重复做两件事:
class MainClass { static byte[] sendBuffer = new byte[1024]; static string sendStr = ""; //监听Socket static Socket listenfd; //客户端Socket及状态信息 static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>(); static void Main(string[] args) { //Socket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ipAdr = IPAddress.Parse("127.0.0.1"); IPEndPoint iPEndPoint = new IPEndPoint(ipAdr,8888); //Bind listenfd.Bind(iPEndPoint); //Listen listenfd.Listen(0); Console.WriteLine("[服务器]启动成功"); while (true) { //检查listenfd,检查是否有用户连接进来 if (listenfd.Poll(0, SelectMode.SelectRead)) { ReadListenfd(listenfd); } //检查clientfd foreach (ClientState cs in clients.Values) { Socket clientfd = cs.socket; if(clientfd.Poll(0, SelectMode.SelectRead)) { if (!ReadClientfd(clientfd)) { break; } } } //防止CPU占用过高,大师依旧会占用大量CPU资源 System.Threading.Thread.Sleep(1); } } /// <summary> /// 读取listenfd,开始Accept /// </summary> /// <param name="listenfd"></param> public static void ReadListenfd(Socket listenfd) { Console.WriteLine("Accept"); Socket clientfd = listenfd.Accept(); ClientState clientState = new ClientState(); clientState.socket = clientfd; clients.Add(clientfd, clientState); } /// <summary> /// 接收客户端消息,并广播给所有客户端 /// </summary> /// <param name="clientfd"></param> /// <returns></returns> public static bool ReadClientfd(Socket clientfd) { ClientState clientState = clients[clientfd]; //接收 int count = 0; try { count = clientfd.Receive(clientState.recvBuffer); } catch (SocketException ex) { clientfd.Close(); Console.WriteLine("Receive SocketException " + ex.ToString()); return false; } //客户端关闭 if(count == 0) { clientfd.Close(); clients.Remove(clientfd); Console.WriteLine("Socket Colse"); return false; } //广播给所有在线的客户端 clientState.recvStr = Encoding.UTF8.GetString(clientState.recvBuffer, 0, count); Console.WriteLine("Receive" + clientState.recvStr); sendStr = clientfd.RemoteEndPoint.ToString() + ":" + clientState.recvStr; Console.WriteLine(clientfd.RemoteEndPoint.ToString()); sendBuffer = Encoding.UTF8.GetBytes(sendStr); foreach (ClientState cs in clients.Values) { cs.socket.Send(sendBuffer); } return true; } }
服务器的代码还有三个注意点:
下一篇:Unity网络游戏编程学习(四)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。