服务器+客户端解决方案
服务器采用一个比较成熟的网络引擎,之前做了N个游戏了..
客户端,好吧,之前有遇到问题,总之思路就是才要那个C#的SOCKET,也不要求多复杂,链接上,单独开一个发包线程,发包使用同步SEND.
收包...这个问题之前是:如果采用线程+同步RECV方法,各种平台(除了手机IOS5 6 7),完全没有问题...但是IPHONE上,同步RECV+线程方式,可能会有时成功有时失败,各种调,仍然不行,表现症状为,如果第一个包收到了,那么后面一切OK,如果第一个包客户端没收到,那么后面就收不到了...实在费解,但是同时发包一切正常.后来的解决方法是收包改用异步收,简简单单的异步收就是了,OK,这次正常了.
核心客户端代码我贴上来,大家看看有没有帮助,组包过程使用到了其他自定义类,大家看着自己处理了,就只贴核心收发链接过程,:
///开始连接-通过IP public static void StartConnectByIP(string _strIP, int _iPort) {///需要启动一个连接线程 s_strIP = _strIP; s_iPort = _iPort; Thread ThreadOfConnectting = new Thread(new ThreadStart(T_Connectting)); ThreadOfConnectting.Start(); s_threadConnect = ThreadOfConnectting; } ///开始连接-通过域名 public static void StartConnectByURL(string _strURL, int _iPort) { s_strURL = _strURL; s_iPort = _iPort; IPHostEntry _ipInfo = Dns.GetHostEntry(s_strURL); IPAddress _ip = _ipInfo.AddressList[0]; s_strIP = _ip.ToString(); Thread ThreadOfConnectting = new Thread(new ThreadStart(T_Connectting)); ThreadOfConnectting.Start(); s_threadConnect = ThreadOfConnectting; } ///发送内容 public static bool SendSomething2Server(Byte[] _byte,int _iSizeCount) { bool _bFlag = false; if(s_pClientSocket != null && s_bStartedSenddingThread && s_threadSend != null) { lock (s_byTeBuffer) { CBaseDataPack _pPac = new CBaseDataPack(_iSizeCount, s_iSeqOfpack, _byte); if (_pPac != null) { if (_pPac.m_iTotalSize < c_iMaxCountBuffer - s_iNumShouldSend) { for (int _iCounter = 0; _iCounter < _pPac.m_iTotalSize; ++_iCounter) { s_byTeBuffer[_iCounter + s_iNumShouldSend] = _pPac.m_strBuffer[_iCounter]; } s_iNumShouldSend += _pPac.m_iTotalSize; ++s_iSeqOfpack; _bFlag = true; } } } } return _bFlag; } /// 连接线程函数--当连接完成的时候线程会退出 /// 实际上可以让其他对象来监视这个线程的运行 /// 时间做超时处理 public static bool s_bIfConnected = false; public static void T_Connectting() { if (s_strIP != null && s_iPort > 0) { s_pClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (s_pClientSocket != null) { IPEndPoint _ie = new IPEndPoint(IPAddress.Parse(s_strIP), s_iPort);//服务器的IP和端口 if (_ie != null) { s_pClientSocket.Connect(_ie); //PhoneScreenLog.AddLineInfo(s_pClientSocket.Available.ToString()); //Thread.Sleep(2000); ///打开收包 ActiveRecvAbout(); ///打开发送线程 ActiveSendAbout(); s_bIfConnected = true; PhoneScreenLog.AddLineInfo("CONNECT DOWN!"); DebugFunc.PrintDebugInfo("Connected!"); } } } } /// 发送线程 public static void T_Sendding() { while (true) { _label: if (!s_pClientSocket.Connected) { Thread.Sleep(1); goto _label; } if (!s_threadSend.IsAlive) { Thread.Sleep(1); s_threadSend.Start(); goto _label; } lock (s_byTeBuffer) { if (s_iNumShouldSend > 0) { int _iNum = s_pClientSocket.Send(s_byTeBuffer, s_iNumShouldSend, SocketFlags.None); if (_iNum < s_iNumShouldSend) { for (int _iCounter = 0; _iCounter < s_iNumShouldSend - _iNum; ++_iCounter) { s_byTeBuffer[_iCounter] = s_byTeBuffer[_iCounter + _iNum]; } } s_iNumShouldSend -= _iNum; } } Thread.Sleep(1); } } ///激活发送线程 public static void ActiveSendAbout() { if (s_pClientSocket != null) { s_pClientSocket.SendTimeout = -1; s_pClientSocket.SendBufferSize = 1024 * 128; if (!s_bStartedSenddingThread) { s_threadSend = new Thread(new ThreadStart(T_Sendding)); if (s_threadSend != null) { s_threadSend.Priority = ThreadPriority.AboveNormal; s_threadSend.Start(); s_bStartedSenddingThread = true; } } } } ///激活收包内容 public static void ActiveRecvAbout() { if (s_pClientSocket != null) { s_pClientSocket.ReceiveTimeout = -1; s_pClientSocket.ReceiveBufferSize = 1024 * 128; if (!s_bStartedRecvedThread) { SetBeginRecv(); s_bStartedRecvedThread = true; //s_threadRecv = new Thread(new ThreadStart(T_Recving)); //if (s_threadRecv != null) //{ // s_threadRecv.Priority = ThreadPriority.AboveNormal; // s_threadRecv.Start(); //} } } } public static void SetBeginRecv() { s_pClientSocket.BeginReceive(s_byRecvBuffer, 0, c_iMaxCountBuffer, SocketFlags.None, new AsyncCallback(s_recvObj.RecvCallBack), null); } /// <summary> /// 收包后的调用器 /// </summary> public class CRecvMachine:object { static object s_objLockOfRecv = new object(); public void RecvCallBack(IAsyncResult ar) { int bytesRead = CClientBaseNet.s_pClientSocket.EndReceive(ar); PhoneScreenLog.AddLineInfo("RECEVE BASA PACKET!:"); PhoneScreenLog.AddLineInfo(bytesRead.ToString()); if(bytesRead > 0) {///对收到的包进行内容上的处理...因为这个函数可能是线程进入...所以 lock (s_objLockOfRecv) { ClientNetDataWrapper.OnRecvedDataFromNetBass(CClientBaseNet.s_byRecvBuffer, bytesRead); } } CClientBaseNet.SetBeginRecv(); } }
浙公网安备 33010602011771号