//Constructor witch can copy an old Client public TV4TcpClient(TV4TcpClient toCopy) : base() { InitThread(); FInput = toCopy.FInput; FEnabled = toCopy.FEnabled; FDoSend = toCopy.FDoSend; FRemoteHost = toCopy.FRemoteHost; FRemotePort = toCopy.FRemotePort; FHoldOutput = toCopy.FHoldOutput; ReceiveBufferSize = toCopy.ReceiveBufferSize; ReceiveTimeout = toCopy.ReceiveTimeout; SendBufferSize = toCopy.SendBufferSize; SendTimeout = toCopy.SendTimeout; }
protected void ProcessInputsSlice(int sliceIndex) { String inputStringSlice; double enabledValueSlice; double doSendValueSlice; String remoteHostStringSlice; double remotePortValueSlice; double holdOutputSlice; double receiveBufferSizeSlice; double receiveTimeoutSlice; double sendBufferSizeSlice; double sendTimeoutSlice; bool remoteHostChangedSlice; bool remotePortChangedSlice; TV4TcpClient tcpClientSlice = TClients[sliceIndex]; //read data from inputs FInputStringInput.GetString(sliceIndex, out inputStringSlice); FEnableValueInput.GetValue(sliceIndex, out enabledValueSlice); FDoSendValueInput.GetValue(sliceIndex, out doSendValueSlice); FRemoteHostStringInput.GetString(sliceIndex, out remoteHostStringSlice); FRemotePortValueInput.GetValue(sliceIndex, out remotePortValueSlice); FHoldOutputInput.GetValue(sliceIndex, out holdOutputSlice); FReceiveBufferSizeInput.GetValue(sliceIndex, out receiveBufferSizeSlice); FReceiveTimeoutInput.GetValue(sliceIndex, out receiveTimeoutSlice); FSendBufferSizeInput.GetValue(sliceIndex, out sendBufferSizeSlice); FSendTimeoutInput.GetValue(sliceIndex, out sendTimeoutSlice); //if the remote server or remote port pin was changed on this slice we're going to have to close //the connection so we can create a new one to the new host and port if (tcpClientSlice.FRemoteHost != null && FRemoteHostStringInput.PinIsChanged) { remoteHostChangedSlice = !(tcpClientSlice.FRemoteHost.Equals(remoteHostStringSlice)); } else { remoteHostChangedSlice = false; } if (FRemotePortValueInput.PinIsChanged) { remotePortChangedSlice = tcpClientSlice.FRemotePort != remotePortValueSlice; } else { remotePortChangedSlice = false; } //if the enabled value changed to zero, we need to close the connection //if the remote server or port pin was changed, we will need to connect to the new host and port if (tcpClientSlice.ConnectStatus != TConnectStatus.NeverConnected && (enabledValueSlice <= 0.5 || remoteHostChangedSlice || remotePortChangedSlice)) { //if the TcpClient object ever connected it cannot be used for another connection, //so we create a new one for any new connection that this slice might make tcpClientSlice.Close(true); tcpClientSlice = TClients[sliceIndex] = new TV4TcpClient(); FOutputStringOutput.SetString(sliceIndex, ""); FConnectedValueOutput.SetValue(sliceIndex, 0); } //we need the data every frame even if none of it has changed, so we store a persistent copy of everything tcpClientSlice.FInput = inputStringSlice; tcpClientSlice.FEnabled = enabledValueSlice > 0.5; tcpClientSlice.FDoSend = doSendValueSlice > 0.5; tcpClientSlice.FRemoteHost = remoteHostStringSlice; tcpClientSlice.FRemotePort = (int)remotePortValueSlice; tcpClientSlice.FHoldOutput = holdOutputSlice > 0.5; tcpClientSlice.ReceiveBufferSize = (int)receiveBufferSizeSlice; tcpClientSlice.ReceiveTimeout = (int)(receiveTimeoutSlice * 1000.0); tcpClientSlice.SendBufferSize = (int)sendBufferSizeSlice; tcpClientSlice.SendTimeout = (int)(sendTimeoutSlice * 1000.0); }
//here we go, thats the method called by vvvv each frame //all data handling should be in here public void Evaluate(int SpreadMax) { //if the slice count has changed if (SpreadMax != FSpreadMax) { int nClients = TClients.Count; //we need a TcpClient instance for every slice if (SpreadMax > nClients) { for (int i = 0; i < SpreadMax - nClients; i++) { TV4TcpClient newClient = new TV4TcpClient(); TClients.Add(newClient); } } else if (SpreadMax < nClients) { //if we have connected TcpClients for extra slices that have been removed, we need to disconnect them for (int i = SpreadMax; i < TClients.Count; i++) { TClients[i].Close(true); //TClients[i] = new TV4TcpClient(); } } } //store the slice count so we can check next frame if it has changed FSpreadMax = SpreadMax; bool anyInputsChanged = FInputStringInput.PinIsChanged || FEnableValueInput.PinIsChanged || FDoSendValueInput.PinIsChanged || FRemoteHostStringInput.PinIsChanged || FRemotePortValueInput.PinIsChanged || FHoldOutputInput.PinIsChanged || FReceiveBufferSizeInput.PinIsChanged || FReceiveTimeoutInput.PinIsChanged || FSendBufferSizeInput.PinIsChanged || FSendTimeoutInput.PinIsChanged; //if any of the inputs has changed if (anyInputsChanged) { //set slicecounts for all outputs //the incoming int SpreadMax is the maximum slicecount of all input pins, which is a good default FOutputStringOutput.SliceCount = SpreadMax; FConnectedValueOutput.SliceCount = SpreadMax; FReceivedNewData.SliceCount = SpreadMax; int requiredBufferSize = 1; //read and process the new input values for (int i = 0; i < SpreadMax; i++) { ProcessInputsSlice(i); //keep track of the largest network buffer size on all of the slices if (TClients[i].ReceiveBufferSize > requiredBufferSize) { requiredBufferSize = TClients[i].ReceiveBufferSize; } } } //since we are always listening for TCP traffic, we have work to do even if none of the inputs have changed for (int i = 0; i < SpreadMax; i++) { try { TV4TcpClient tcpClientSlice = TClients[i]; FReceivedNewData.SetValue(i, 0); //if the connection is enabled if (tcpClientSlice.FEnabled) { //if the connection hasn't been made yet, try to connect asynchronously if (tcpClientSlice.ConnectStatus == TConnectStatus.NeverConnected) { tcpClientSlice.BeginConnectAndTrackStatus(); } //if we didn't read anything and we're not holding the last read value, //clear the output pin if (!tcpClientSlice.FHoldOutput) { FOutputStringOutput.SetString(i, ""); } if (tcpClientSlice.ConnectStatus == TConnectStatus.Connected) { //set ConnectPin to 1 FConnectedValueOutput.SetValue(i, 1); //-- send -- if (tcpClientSlice.FInput != null) { if (tcpClientSlice.FDoSend) { tcpClientSlice.Send(); } } // -- Read -- if (tcpClientSlice.IsReading == false) { string dataReceived = tcpClientSlice.GetReadData(); if (dataReceived != null) { FReceivedNewData.SetValue(i, 1); FOutputStringOutput.SetString(i, dataReceived); //Debug.WriteLine("Length: " + dataReceived.Length); } tcpClientSlice.Read(); } } if (tcpClientSlice.ConnectStatus == TConnectStatus.ConnectionLost || tcpClientSlice.ConnectStatus == TConnectStatus.Disconnected) { FConnectedValueOutput.SetValue(i, 0); //the TcpClient object is now useless so we create a new one to try to reconnect next time //we copy all the data values from the old client object, but not the actual tcp stream object TV4TcpClient newClient = new TV4TcpClient(tcpClientSlice); tcpClientSlice.Close(true); tcpClientSlice = TClients[i] = newClient; } } //update the "connected" output pin to show whether we are connected FConnectedValueOutput.SetValue(i, tcpClientSlice.Connected ? 1.0 : 0.0); //Reading Error MEssages formt the TCPClient Class List <string> Errors; Errors = tcpClientSlice.GetErrorMessages(); if (Errors != null) { foreach (string Error in Errors) { FHost.Log(TLogType.Error, Error); } } } catch (Exception ex) { FHost.Log(TLogType.Error, ex.Message); } } }