Autor |
Beitrag |
winx
Beiträge: 249
|
Verfasst: Mo 10.12.07 12:09
Hi,
ich habe einen Server der per TCP/IP mit Clients kommuniziert. Daten anmelden,senden & empfangen funktioniert einwandfrei.
Mein Problem ist nun das der Server anscheinend selbstständig die Verbindung zum Client trennt... wie kann sowas vorkommen,
bzw welche Einstellungen am Socket muß ich treffen, damit sowas nicht mehr passiert?
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495:
| using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.Windows.Forms; using Server.GUI; using Remoting; using log4net;
namespace Server.TcpIP {
delegate void SetReceivedText(string text);
delegate void AddProcessState(string text); delegate void ClearProcessStates(); delegate void StartListening();
internal class TCPIPServer {
#region private Members private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private CommandRemoting m_CommandRemotingObject;
private SocketServerForm m_ServerForm;
public SocketServerForm ServerForm { get { return m_ServerForm; } }
private Socket m_ListenForClientsSocket;
private int m_clientCount = 0;
const int MAX_CLIENTS = 100;
private ClientManager m_ClientManager;
#endregion
#region Constructor and Singleton Instance Function
internal TCPIPServer(CommandRemoting crObject) { m_CommandRemotingObject = crObject; init(); }
internal TCPIPServer() { init(); }
#endregion
#region private Functions
private void init() { m_ClientManager = new ClientManager(); m_ServerForm = new SocketServerForm(); m_ServerForm.textBoxIP.Text = Properties.Settings.Default.HostIP; m_ServerForm.textBoxPort.Text = Properties.Settings.Default.ServerListenerPort.ToString();
m_CommandRemotingObject.setServerAndPort(Properties.Settings.Default.HostIP, Properties.Settings.Default.ServerListenerPort.ToString());
m_ServerForm.buttonClose.Click += new EventHandler(buttonClose_Click); m_ServerForm.buttonStartListen.Click += new EventHandler(buttonStartListen_Click); m_ServerForm.buttonStopListen.Click += new EventHandler(buttonStopListen_Click); m_ServerForm.buttonSendMsg.Click += new EventHandler(buttonSendMsg_Click); m_CommandRemotingObject.StartServerEvent += new StartServer(m_CommandRemotingObject_StartServerEvent); m_CommandRemotingObject.StopServerEvent += new StopServer(m_CommandRemotingObject_StopServerEvent); }
void m_CommandRemotingObject_StopServerEvent() { this.CloseSockets(); }
void m_CommandRemotingObject_StartServerEvent() { this.startListening(); }
#region private event Functions (Events vom Formular) private void buttonStartListen_Click(object sender, EventArgs e) { }
public void startListening() { if (m_ServerForm.InvokeRequired) { m_ServerForm.Invoke(new StartListening(startListening)); return; }
try { if (m_ServerForm.textBoxPort.Text == "") { MessageBox.Show("Please enter a Port Number"); return; } string portStr = m_ServerForm.textBoxPort.Text; int port = System.Convert.ToInt32(portStr); m_ListenForClientsSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress hostIPAddress = IPAddress.Parse(Properties.Settings.Default.HostIP); IPEndPoint ipLocal = new IPEndPoint(hostIPAddress, port); m_ListenForClientsSocket.Bind(ipLocal); m_ListenForClientsSocket.Listen(4); m_ListenForClientsSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
UpdateControls(true);
} catch (SocketException se) { Logger.Error(se.Message); } }
void buttonSendMsg_Click(object sender, EventArgs e) { try { Object objData = m_ServerForm.richTextBoxSendMsg.Text; byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString()); foreach (Client client in m_ClientManager.Clients) {
if ((client != null) && (client.ClientSocket != null)) {
if (client.ClientSocket.Connected) { client.ClientSocket.Send(byData); } }
}
} catch (SocketException se) { Logger.Error(se.Message); } }
void buttonStopListen_Click(object sender, EventArgs e) { CloseSockets(); UpdateControls(false); }
private void buttonClose_Click(object sender, EventArgs e) { CloseSockets(); m_ServerForm.Close(); }
#endregion
public void UpdateControls(bool listening) { m_ServerForm.buttonStartListen.Enabled = !listening; m_ServerForm.buttonStopListen.Enabled = listening; }
private void OnClientConnect(IAsyncResult asyn) { try { Socket newSocket = m_ListenForClientsSocket.EndAccept(asyn);
Logger.Debug("New Client Connection (IP: " + newSocket.RemoteEndPoint.ToString() + ", Port: " + ((IPEndPoint)newSocket.LocalEndPoint).Port.ToString() + ")"); m_CommandRemotingObject.newClientConnected(newSocket.RemoteEndPoint.ToString()); Client newClient = new Client(newSocket);
m_ClientManager.Clients.Add(newClient);
newClient.WaitForData(); ++m_clientCount; String str = String.Format("Client # {0} connected", m_clientCount);
setTextBoxMsgText(str);
m_ListenForClientsSocket.BeginAccept(new AsyncCallback(OnClientConnect), null); } catch (ObjectDisposedException) { System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n"); } catch (SocketException se) { Logger.Error(se.Message); }
}
private String GetIP() { String strHostName = Dns.GetHostName();
IPHostEntry iphostentry = Dns.GetHostEntry(strHostName);
String IPStr = ""; foreach (IPAddress ipaddress in iphostentry.AddressList) { IPStr = ipaddress.ToString(); return IPStr; } return IPStr; }
private void CloseSockets() { if (m_ListenForClientsSocket != null) { m_ListenForClientsSocket.Close(); }
while (m_ClientManager.Clients.Count > 0) { if (m_ClientManager.Clients[0] != null) { m_ClientManager.Clients[0].ClientSocket.Close(); m_ClientManager.Clients.Remove(m_ClientManager.Clients[0]); } } }
#region Invoke Funktionen zum Zugriff auf Formularkomponenten
private void appendTextToReceivedTextBoxSPS(string text) { if (m_ServerForm.richTextBoxReceivedMsgFromSPS.InvokeRequired) { m_ServerForm.richTextBoxReceivedMsgFromSPS.Invoke(new SetReceivedText(appendTextToReceivedTextBoxSPS), new object[] { text }); return; }
m_ServerForm.richTextBoxReceivedMsgFromSPS.AppendText(text);
}
public void appendTextToReadyWTBox(string szData) { if (m_ServerForm.richTextBoxReadyWTs.InvokeRequired) { m_ServerForm.richTextBoxReadyWTs.Invoke(new SetReceivedText(appendTextToReadyWTBox), new object[] { szData }); return; }
m_ServerForm.richTextBoxReadyWTs.AppendText(szData+"\r\n"); }
private void setTextBoxMsgText(string text) { if (m_ServerForm.textBoxMsg.InvokeRequired) { m_ServerForm.textBoxMsg.Invoke(new SetReceivedText(setTextBoxMsgText), new object[] { text }); return; }
m_ServerForm.textBoxMsg.Text = text;
} #endregion
#endregion
#region public Functions
public void showForm() { if (m_ServerForm != null) { m_ServerForm.Show(); } }
public void addProcessState(string state) { if (m_ServerForm.InvokeRequired) { m_ServerForm.Invoke(new AddProcessState(addProcessState), new Object[] { state }); return; }
m_ServerForm.richTextBoxProcessState.Text = m_ServerForm.richTextBoxProcessState.Text + "\r\n" + state; }
public void clearProcessStates() { if (m_ServerForm.InvokeRequired) { m_ServerForm.Invoke(new ClearProcessStates(clearProcessStates)); return; }
m_ServerForm.richTextBoxProcessState.Text = String.Empty;
}
#endregion } } |
Jeder "Client" wird dabei in einer eigenen Klasse verwaltet, die das Senden & Empfangen managed:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432:
| using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using Server.Commands; using Server.Utility;
namespace Server.TcpIP {
internal class Client {
#region private Members
private Socket m_ClientSocket; private AsyncCallback m_AsyncCallbackFunction; private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private string m_IP; private string m_receivedData = String.Empty;
#endregion
#region Properties
public Socket ClientSocket { get { return m_ClientSocket; } set { m_ClientSocket = value; } }
public AsyncCallback AsyncCallbackFunction { get { return m_AsyncCallbackFunction; } set { m_AsyncCallbackFunction = value; } }
public string IP { get { return m_IP; } }
#endregion
#region Constructor and Singleton Instance Function
internal Client(Socket sock) { m_ClientSocket = sock; m_IP = sock.RemoteEndPoint.ToString(); Processing.ProcessHandler.Instance.DistanceReadReadyEvent += new Server.Processing.DistanceReadReady(Instance_DistanceReadReadyEvent); Processing.ProcessHandler.Instance.CamReadyEvent += new Server.Processing.CamReady(Instance_CamReadyEvent); Processing.ProcessHandler.Instance.MarkingReadyEvent += new Server.Processing.MarkingReady(Instance_MarkingReadyEvent); Processing.ProcessHandler.Instance.ErrorOccuredEvent += new Server.Processing.ErrorOccured(Instance_ErrorOccuredEvent); Processing.ProcessHandler.Instance.SwitchOnLightEvent += new Server.Processing.SwitchOnLight(Instance_SwitchOnLightEvent); CommandFactory.Instance.CommandErrorEvent += new CommandError(Instance_CommandErrorEvent);
}
void Instance_SwitchOnLightEvent(int situation) { }
#endregion
#region private Functions
public void WaitForData() { try {
if (m_AsyncCallbackFunction == null) { this.m_AsyncCallbackFunction = new AsyncCallback(OnDataReceived); }
SocketPacket theSocPkt = new SocketPacket(); theSocPkt.CurrentSocket = this.m_ClientSocket;
this.m_ClientSocket.BeginReceive(theSocPkt.DataBuffer, 0, theSocPkt.DataBuffer.Length, SocketFlags.None, m_AsyncCallbackFunction, theSocPkt);
} catch (SocketException se) {
Logger.Error(se.Message); }
}
private void OnDataReceived(IAsyncResult asyn) { try { SocketPacket socketData = (SocketPacket)asyn.AsyncState;
int iRx = 0; iRx = socketData.CurrentSocket.EndReceive(asyn); char[] chars = new char[iRx + 1]; System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder(); int charLen = d.GetChars(socketData.DataBuffer, 0, iRx, chars, 0); System.String szData = new System.String(chars);
if ((m_NewCommandStarted == false)&&(szData.Contains(Utility.Constants.cStartSign))) { m_receivedData = Utility.Constants.cStartSign; m_NewCommandStarted = true; } else m_receivedData += szData[0]; if ( (m_receivedData.EndsWith(Utility.Constants.cEndSign)) && (m_NewCommandStarted)) { m_NewCommandStarted = false; StringBuilder builder = new StringBuilder(m_receivedData); commandReceived(builder.ToString()); m_receivedData = String.Empty;
}
WaitForData(); } catch (ObjectDisposedException) { System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n"); } catch (SocketException se) { Logger.Error(se.Message); } }
private bool m_NewCommandStarted = false;
private void commandReceived(string receivedCommandString) {
Logger.Error("********************************************************"); string commandString = receivedCommandString.Replace("\0",""); commandString = commandString.Replace(" ", "");
Logger.Error("Command received'n'cut : [" + commandString + "]"); Logger.Error("********************************************************");
if (receivedCommandString.Equals(Constants.cConnectedCommandReceive)) { this.sendData(Constants.cConnectedCommandAnswer); return; }
if (receivedCommandString.Equals(Constants.cLampCommandReceive)) { return; }
CommandFactory.Instance.newCommandReceived(commandString, this.m_IP);
}
private void Instance_DistanceReadReadyEvent(Server.Processing.ProcessItem pi) {
string answer = createStationAnswerCommand(pi, String.Empty); sendData(answer); }
void Instance_MarkingReadyEvent(Server.Processing.ProcessItem pi) { string answer = createStationAnswerCommand(pi, String.Empty); sendData(answer); }
void Instance_CamReadyEvent(Server.Processing.ProcessItem pi) { string answer = createStationAnswerCommand(pi, String.Empty); sendData(answer); }
void Instance_ErrorOccuredEvent(Server.Processing.ProcessItem pi, string station) { return; string answer = createStationAnswerCommand(pi, station); sendData(answer);
}
void Instance_CommandErrorEvent(int errorCode) { return; string answer = Constants.cStartSign + "0" + Constants.cDelimiter +Constants.cError +Constants.cDelimiter + errorCode + Constants.cEndSign; sendData(answer);
}
private string createStationAnswerCommand(Server.Processing.ProcessItem pi, String errorStation) { string answer = Constants.cStartSign; if (pi == null) {
answer = answer + "0"; answer = answer + Constants.cDelimiter; answer = answer + errorStation; answer = answer + Constants.cDelimiter; answer = answer + "0"; } else {
answer = answer + pi.ID; answer = answer + Constants.cDelimiter; if (pi.ProcessState.Equals(Processing.ProcessStates.EmptyWTDetected)) {
answer = answer + pi.StationCommand.Station; answer = answer + Constants.cDelimiter; if (pi.StationCommand.Station.Equals(Constants.cDistance)) answer = answer + Constants.cEmptyWT; else answer = answer + "0"; } else if (pi.ProcessState.Equals(Processing.ProcessStates.ErrorOccured)) { answer = answer + errorStation; answer = answer + Constants.cDelimiter; answer = answer + pi.ErrorCode.ToString(); } else { answer = answer + pi.StationCommand.Station; answer = answer + Constants.cDelimiter; answer = answer + "0"; }
} answer = answer + Constants.cEndSign; return answer;
}
private bool m_SendToSPSLock = false;
private void sendData(string data) { try { while (m_SendToSPSLock) { System.Threading.Thread.Sleep(200); }
m_SendToSPSLock = true;
Object objData = data; byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString()); m_receivedData = String.Empty; try { m_ClientSocket.Send(byData); Logger.Info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); Logger.Info("Data send to SPS: [" + data+"]"); Logger.Info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); } catch (Exception e) { Logger.Error("Client disconnected: "+e.Message); } } finally { m_SendToSPSLock = false; }
} #endregion
#region public Functions
#endregion
} } |
Danke für jeglich Tipps (auch wenn der Sourceode vielleicht gar nich nötig ist) !!!
gruß,
winx
|
|
Kha
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 10.12.07 14:13
Kenne mich mit dem Zeugs nicht aus, aber wird deine Serverklasse möglicherweise einfach vom GC freigegeben? So oder so sollte sie wohl IDisposable implementieren, da das ihr Socket ebenfalls macht.
|
|
winx
Beiträge: 249
|
Verfasst: Di 11.12.07 10:28
Hi,
Ich poste hier mal Ausschnitte aus meinem Logfile.
sowohl beim Senden als auch beim Empfangen:
2007-12-07 13:17:32,296 [21] Client.sendData: Client disconnected: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
2007-12-07 13:16:34,687 [3] Client.OnDataReceived: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
Also irgendwie unregelmäßig und auch nicht nach langer Inaktivität:
Zum Beispiel hier:
2007-12-07 13:16:34,687 [3] Client.OnDataReceived: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
2007-12-07 13:16:40,265 [3] TCPIPServer.OnClientConnect: New Client Connection (IP: 172.16.2.166:5, Port: 8000)
2007-12-07 13:16:40,296 [3] Client.commandReceived: Command received
wurde die Verbindung zuerst unterbrochen, dann hat sich der Client wieder vebunden und was erfolgreich gesendet.
kurze Zeit später hat er wieder was erflogreich empfangen, aber beim Senden dann der Fehler:
2007-12-07 13:17:23,609 [3] Client.commandReceived: Command received
2007-12-07 13:17:23,656 [24] Client.sendData: Client disconnected: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
Also irgendwie ganz, ganz kurios... aber der GC kann doch nicht einfach so schnell was freigeben, oder???
Danke für weitere Tipps,
winx
|
|
|