私はC#アプリケーションでBeginSendとBeginReceiveの両方を使用しています。これはクライアントリスナーであり、サーバーからのみデータを受信します。私はBeginReceiveを使ってデータを取得しています。C#ソケット接続のBeginSendとBeginReceiveの問題
しかし、受信を行うだけでは接続を生き生きとして安定に保つことができないことがわかりました。だから、私は、BeginSendを使って接続を維持するために、私のアプリケーションで常にサーバにpingすることを決めました。以下は
は私のコードです:
private void timer1_Tick(object sender, EventArgs e)
{
DataProcess();
}
public Socket _serverSocket = null;
private byte[] _recieveBuffer = new byte[128];
byte[] AllBytes;
void DataProcess()
{
//TimeSpan ts;
try
{
//Thread.Sleep(100);
if (_serverSocket == null || sockState == MySocketState.Disconnected)
{
Console.WriteLine("Trying to connect...");
SetupServer();
}
else
{
AllBytes = ASCIIEncoding.ASCII.GetBytes(COM_DeviceIsOnline);
_serverSocket.BeginSend(AllBytes, 0, AllBytes.Length, SocketFlags.None, new AsyncCallback(SendCallback), null);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private void SetupServer()
{
try
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Connect(_sIP, Int32.Parse(_sPort));
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
}
if (_serverSocket.Connected)
{
sockState = MySocketState.Connected;
browser.ExecuteScriptAsync("svrConnect();");
Console.WriteLine("Server connected...");
_serverSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
}
void SendCallback(IAsyncResult ar)
{
try
{
int bytesSent = _serverSocket.EndSend(ar);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private void ReceiveCallback(IAsyncResult AR)
{
try
{
if (_serverSocket == null)
_serverSocket = (Socket)AR.AsyncState;
//Check how much bytes are recieved and call EndRecieve to finalize handshake
int recieved = _serverSocket.EndReceive(AR);
if (recieved <= 0)
{
CloseSocket();
return;
}
//Copy the recieved data into new buffer , to avoid null bytes
byte[] recData = new byte[recieved];
Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);
string strData = ASCIIEncoding.ASCII.GetString(recData);
Console.WriteLine(strData);
//Process data here the way you want , all your bytes will be stored in recData
int nSOHPos = -1;
int nSTXPos = -1;
int nETXPos = -1;
int nEOTPos = -1;
nSOHPos = Array.IndexOf(recData, SOH);
nSTXPos = Array.IndexOf(recData, STX);
nETXPos = Array.IndexOf(recData, ETX);
nEOTPos = Array.IndexOf(recData, EOT);
if ((nSOHPos == -1) || (nSTXPos == -1) || (nETXPos == -1) || (nEOTPos == -1))
{
CloseSocket();
return;
}
if (nSOHPos > nSTXPos ||
nSTXPos > nETXPos ||
nETXPos > nEOTPos)
{
CloseSocket();
return;
}
if ((nETXPos - nSTXPos) < 6)
{
CloseSocket();
return;
}
string _sCommand = ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 6, 2);
if ((_sCommand == "CN") || (_sCommand == "CL") || (_sCommand == "CR"))
{
nDept = int.Parse(ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 12, 2));
if (nDept != dept_id) return;
nCntr = int.Parse(ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 14, 2));
nServ = int.Parse(ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 16, 2));
sQnum = ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 8, 4);
string[] sSplit = strData.Split('^');
string sCusName = sSplit[1];
//if (_sCommand == "CR") sCusName = " ";
Console.WriteLine("Dept ID = " + nDept);
Console.WriteLine("Cntr ID = " + nCntr);
Console.WriteLine("Serv ID = " + nServ);
Console.WriteLine("Queue No = " + sQnum);
Console.WriteLine("Cus Name = " + sCusName);
var script = string.Format("nextCall(\'{0}\', {1}, {2});", sQnum, nCntr, nServ);
browser.ExecuteScriptAsync(script);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
CloseSocket();
}
finally
{
try
{
//Start receiving again
if (_serverSocket != null)
_serverSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
//theDevSock.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, ReceiveCallback, theDevSock);
}
catch (Exception ex2)
{ }
}
}
public void CloseSocket()
{
try
{
if (_serverSocket != null)
{
if (_serverSocket.Connected)
_serverSocket.Shutdown(SocketShutdown.Both);
_serverSocket.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
_serverSocket = null;
sockState = MySocketState.Disconnected;
browser.ExecuteScriptAsync("svrDisconnect();");
}
私のアプリケーションは、私は、サーバーへの接続を開始します。サーバーに接続すると、サーバーのpingが開始されます。しかし、BeginSendを使用してサーバーにpingを実行するたびに、「スレッド0x1ff0がコード259(0x103)で終了しました」というエラーが発生しました。サーバーへの接続が切断され、アプリケーションがサーバーへの接続を再試行します。その後、正常に接続した後、再度pingを実行すると、再び切断されます。
私のコーディングは正しく書かれていますか?このようなBeginSendをpingサーバーに使用できますか?
'SetSocketOption'メソッドを使用して接続を維持するには、次のようにします:' socket.SetSocketOption(SocketOptionLevel.Tcp、SocketOptionLevel.Tcp、SocketOptionName.KeepAlive、true); ' – raidensan
このコーディングの行はどこに追加しますか?お勧めできますか? – Coolguy
これは本当にあなたのアプリケーションのロジックに依存しますが、一般的なアプローチは接続する前にソケットオプションを設定することです。 – raidensan