//阻塞式连接,使用默认Ip端口进行连接 public ServiceModel.SOCKET_CODE SocketConnect() { //如果Socket未初始化且不是绑定状态 if (ServiceModel.BASESOCKET_STATE.SOCKET_INITING != state && ServiceModel.BASESOCKET_STATE.SOCKET_BINDING != state) { return(ServiceModel.SOCKET_CODE.ERROR_STATE); } IPAddress addr = IPAddress.Parse(MyCentorl.Ip.Trim()); try { //使用默认的端口和地址进行连接 socket.Connect(addr, MyCentorl.Port); } catch (Exception e) { state = ServiceModel.BASESOCKET_STATE.SOCKET_ERROR; return(ServiceModel.SOCKET_CODE.ERROR_CONNECT); } //连接成功更新状态为已连接 state = ServiceModel.BASESOCKET_STATE.SOCKET_CONNECTING; //启动接收 StartRecv(); return(ServiceModel.SOCKET_CODE.SUCCESS); }
//异步发送数据 public ServiceModel.SOCKET_CODE SocketSend(byte[] data, int offset, int size) { //只有以下两种情况可以发送数据 //1.当我是服务器,我可以对已经连接上我的客户端进行发送数据 //2.当我是客户端,且已经连接上服务器 //tcp服务端套接字只能用于接收连接,无法用于发送数据 if (ServiceModel.BASESOCKET_STATE.SOCKET_CONNECTING != state) { return(ServiceModel.SOCKET_CODE.ERROR_STATE); } try { socket.BeginSend(data, offset, size, SocketFlags.None, new AsyncCallback(OnSend), null); } //当发生套接字错误,表示该套接字已经出现异常 catch { state = ServiceModel.BASESOCKET_STATE.SOCKET_ERROR; return(ServiceModel.SOCKET_CODE.ERROR_SOCKET); } return(ServiceModel.SOCKET_CODE.SUCCESS); }
private byte[] backupBuffer = null; //备份缓冲区,用来缓存半包 public void NetWork_TCP() { socket = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, ProtocolType.Tcp); state = ServiceModel.BASESOCKET_STATE.SOCKET_INITING; socket.SendTimeout = 500; }
private void OnRecv(IAsyncResult ar) { try { int recvLength = socket.EndReceive(ar); int pkgLength = 0; byte[] data; //如果半包数据不为空 if (null != backupBuffer) { //将半包和后面接收到的数据报拼接起来 data = backupBuffer.Concat(recvBuffer.Take(recvLength).ToArray()).ToArray(); } else { data = recvBuffer.Take(recvLength).ToArray(); } //解决连包问题 while (true) { // 1. recvEvent返回一个完整的数据包长度 pkgLength = MyCentorl.RecvMessage(data); if (pkgLength <= 0 || pkgLength > maxPackage) { //出现异常,连接关闭 state = ServiceModel.BASESOCKET_STATE.SOCKET_ERROR; Close(); break; } // 2. 如果正常处理完,则直接启动下次接收 if (pkgLength == data.Length) { ////TraceUtil.Log("正常"); backupBuffer = null; Array.Clear(recvBuffer, 0, recvBuffer.Length); pkgLength = 0; break; } // 3. 如果还未接收完,半包则在偏移处等待 else if (pkgLength > data.Length) { //将半包数据拷贝到backupBuffer ////TraceUtil.Log("半包"); backupBuffer = data.Take(data.Length).ToArray(); break; } // 4. 如果是连包,则循环处理 else if (pkgLength < data.Length) { //自增偏移量并跳过已经处理的包 ////TraceUtil.Log("连包"); data = data.Skip(pkgLength).ToArray(); backupBuffer = null; } else { break; } } StartRecv(); } catch { state = ServiceModel.BASESOCKET_STATE.SOCKET_ERROR; Close(); } }