You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
5.4 KiB
180 lines
5.4 KiB
/*
|
|
Sog 游戏基础库
|
|
2016 by zouwei
|
|
*/
|
|
|
|
|
|
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
namespace SogClient
|
|
{
|
|
public class TcpClientSession : ClientSession
|
|
{
|
|
protected ConnectedClientSessionUpdate m_sessionUpdate;
|
|
|
|
public TcpClientSession(ClientSessionSettings clientSettings,
|
|
ConnectedClientSessionUpdate updateMgr, SessionNetSelectMode mode)
|
|
:base(clientSettings)
|
|
{
|
|
AllockSocket();
|
|
m_sessionUpdate = updateMgr;
|
|
NetSessionObj = new TcpSession(m_socketClient);
|
|
|
|
}
|
|
|
|
private void AllockSocket()
|
|
{
|
|
m_socketClient = new Socket(m_clientSettings.RemoteEndPoint.AddressFamily,
|
|
SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
m_socketClient.Blocking = false;
|
|
|
|
m_socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
|
|
}
|
|
|
|
public override void Connect()
|
|
{
|
|
TraceLog.Trace("TcpClientSession.Connect from local {1} to remote {0} sessionID:{2}", m_clientSettings.RemoteEndPoint, NetSessionObj.LocalEndPoint, NetSessionObj.SessionID);
|
|
|
|
m_isConnected = false;
|
|
m_isConnecting = true;
|
|
|
|
|
|
bool connFail = false;
|
|
try
|
|
{
|
|
m_socketClient.Connect(m_clientSettings.RemoteEndPoint);
|
|
}
|
|
catch (ObjectDisposedException ex)
|
|
{
|
|
TraceLog.Error("TcpClientSession.Connect {0} ObjectDisposedException message {1}",
|
|
m_clientSettings.RemoteEndPoint, ex.Message);
|
|
|
|
connFail = true;
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
TraceLog.Error("TcpClientSession.Connect {0} InvalidOperationException message {1}",
|
|
m_clientSettings.RemoteEndPoint, ex.Message);
|
|
|
|
connFail = true;
|
|
}
|
|
catch (SocketException ex)
|
|
{
|
|
// 返回 WouldBlock 是正常的,微软官方解释: An operation on a nonblocking socket cannot be completed immediately.
|
|
// 但是返回其他异常呢?
|
|
TraceLog.Trace("TcpClientSession.Connect {0}, wait connected finish SocketErrorCode {1},",
|
|
m_clientSettings.RemoteEndPoint, ex.SocketErrorCode);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TraceLog.Error("TcpClientSession.Connect {0} fail, exception {1}"
|
|
, m_clientSettings.RemoteEndPoint, ex);
|
|
|
|
connFail = true;
|
|
}
|
|
|
|
if (connFail)
|
|
{
|
|
TraceLog.Error("TcpClientSession.Connect connFail is True! ");
|
|
TcpConnectFail();
|
|
}
|
|
}
|
|
|
|
public override void Reconnect()
|
|
{
|
|
TraceLog.Trace("TcpClientSession.Reconnect from local {1} to remote {0} sessionID:{2}", m_clientSettings.RemoteEndPoint, NetSessionObj.LocalEndPoint, NetSessionObj.SessionID);
|
|
|
|
// 重连时m_socketClient如果不是null,要丢掉session中未发送和未解析的信息
|
|
if (m_socketClient != null)
|
|
{
|
|
TraceLog.Error("TcpClientSession.Reconnect close old socket");
|
|
CloseSession();
|
|
}
|
|
|
|
//重连的时候重新allock socket,linux下必须如此
|
|
AllockSocket();
|
|
|
|
Connect();
|
|
}
|
|
|
|
private void TcpConnectFail()
|
|
{
|
|
TraceLog.Trace("TcpClientSession : TcpConnectFail");
|
|
CloseSession();
|
|
|
|
SessionEventArgs arg = new SessionEventArgs();
|
|
arg.Session = NetSessionObj;
|
|
OnConnectFail(arg);
|
|
}
|
|
|
|
public override void Update(long nowMs)
|
|
{
|
|
UpdateConnect();
|
|
UpdateReadWrite();
|
|
}
|
|
|
|
public void UpdateConnect()
|
|
{
|
|
|
|
if (!m_isConnecting)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool bError = m_socketClient.Poll(0, SelectMode.SelectError);
|
|
if (bError)
|
|
{
|
|
TraceLog.Trace("TcpClientSession.UpdateConnect bError is True! sessionId:{0}", NetSessionObj.SessionID);
|
|
TcpConnectFail();
|
|
}
|
|
else
|
|
{
|
|
bool bWrite = m_socketClient.Poll(0, SelectMode.SelectWrite);
|
|
if(bWrite)
|
|
{
|
|
ConnectSucc();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void UpdateReadWrite()
|
|
{
|
|
if (m_socketClient == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (m_isConnected)
|
|
{
|
|
if (NetSessionObj.IsSocketClosed)
|
|
{
|
|
OnUpdateConnectedSocketError();
|
|
return;
|
|
}
|
|
|
|
m_sessionUpdate.AddToList(this);
|
|
}
|
|
}
|
|
|
|
protected override void CloseSession()
|
|
{
|
|
TraceLog.Trace("TcpClientSession.CloseSession session {0}"
|
|
, NetSessionObj.SessionID);
|
|
|
|
m_isConnected = false;
|
|
m_isConnecting = false;
|
|
|
|
//丢弃正在发送和接收的数据,关闭socket
|
|
NetSessionObj.Close();
|
|
m_socketClient = null;
|
|
}
|
|
}
|
|
}
|