Revert "Use socket instead of TcpClient and stream."

Revert back to using Stream/TcpClient. High performance stuff is moved
to highperformancesockets branch. I think this is interesting, but i also
feel that this is premature optimization. I doubth that this will be a
performance bottleneck ofr the forseeable future.

This reverts commit 1b34716a30.
This commit is contained in:
Thomas Jäger
2018-05-18 08:49:43 +02:00
parent 219c1cc71a
commit 64e485c54a
10 changed files with 186 additions and 318 deletions

View File

@@ -4,7 +4,6 @@ using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using S7.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading.Tasks;
@@ -14,22 +13,18 @@ namespace S7.Net.UnitTest
[TestClass]
public class ProtocolUnitTest
{
/*
* Not sure how to implment these tests cleanly now. Probably need to spin up a TcpServer.
[TestMethod]
public void TPKT_Read()
{
Socket s = new Socket(SocketType.Stream, ProtocolType.Tcp);
s.Send(StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"));
//Socket m = new MemoryStream();
var t = TPKT.Read(s);
Assert.AreEqual(0x03, t.Version);
Assert.AreEqual(0x29, t.Length);
//m.Position = 0;
//t = TPKT.ReadAsync(m).Result;
//Assert.AreEqual(0x03, t.Version);
//Assert.AreEqual(0x29, t.Length);
}
[TestMethod]
public void TPKT_Read()
{
var m = new MemoryStream(StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"));
var t = TPKT.Read(m);
Assert.AreEqual(0x03, t.Version);
Assert.AreEqual(0x29, t.Length);
m.Position = 0;
t = TPKT.ReadAsync(m).Result;
Assert.AreEqual(0x03, t.Version);
Assert.AreEqual(0x29, t.Length);
}
[TestMethod]
[ExpectedException(typeof(TPKTInvalidException))]
@@ -58,7 +53,7 @@ namespace S7.Net.UnitTest
t = COTP.TSDU.ReadAsync(m).Result;
Assert.IsTrue(expected.SequenceEqual(t));
}
*/
private static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
@@ -66,7 +61,5 @@ namespace S7.Net.UnitTest
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
}
}

View File

@@ -162,15 +162,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClass tc = new TestClass
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestClass tc = new TestClass();
tc.BitVariable00 = true;
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariable = -154.789;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
TestClass tc2 = new TestClass();
// Values that are read from a class are stored inside the class itself, that is passed by reference
@@ -191,15 +189,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestStruct tc = new TestStruct
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestStruct tc = new TestStruct();
tc.BitVariable00 = true;
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariable = -154.789;
tc.DWordVariable = 850;
plc.WriteStruct(tc, DB2);
// Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
TestStruct tc2 = (TestStruct)plc.ReadStruct(typeof(TestStruct), DB2);
@@ -219,33 +215,31 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestLongStruct tc = new TestLongStruct
{
IntVariable0 = 0,
IntVariable1 = 1,
IntVariable10 = 10,
IntVariable11 = 11,
IntVariable20 = 20,
IntVariable21 = 21,
IntVariable30 = 30,
IntVariable31 = 31,
IntVariable40 = 40,
IntVariable41 = 41,
IntVariable50 = 50,
IntVariable51 = 51,
IntVariable60 = 60,
IntVariable61 = 61,
IntVariable70 = 70,
IntVariable71 = 71,
IntVariable80 = 80,
IntVariable81 = 81,
IntVariable90 = 90,
IntVariable91 = 91,
IntVariable100 = 100,
IntVariable101 = 101,
IntVariable110 = 200,
IntVariable111 = 201
};
TestLongStruct tc = new TestLongStruct();
tc.IntVariable0 = 0;
tc.IntVariable1 = 1;
tc.IntVariable10 = 10;
tc.IntVariable11 = 11;
tc.IntVariable20 = 20;
tc.IntVariable21 = 21;
tc.IntVariable30 = 30;
tc.IntVariable31 = 31;
tc.IntVariable40 = 40;
tc.IntVariable41 = 41;
tc.IntVariable50 = 50;
tc.IntVariable51 = 51;
tc.IntVariable60 = 60;
tc.IntVariable61 = 61;
tc.IntVariable70 = 70;
tc.IntVariable71 = 71;
tc.IntVariable80 = 80;
tc.IntVariable81 = 81;
tc.IntVariable90 = 90;
tc.IntVariable91 = 91;
tc.IntVariable100 = 100;
tc.IntVariable101 = 101;
tc.IntVariable110 = 200;
tc.IntVariable111 = 201;
plc.WriteStruct(tc, DB2);
Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
// Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
@@ -285,33 +279,31 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestLongClass tc = new TestLongClass
{
IntVariable0 = 0,
IntVariable1 = 1,
IntVariable10 = 10,
IntVariable11 = 11,
IntVariable20 = 20,
IntVariable21 = 21,
IntVariable30 = 30,
IntVariable31 = 31,
IntVariable40 = 40,
IntVariable41 = 41,
IntVariable50 = 50,
IntVariable51 = 51,
IntVariable60 = 60,
IntVariable61 = 61,
IntVariable70 = 70,
IntVariable71 = 71,
IntVariable80 = 80,
IntVariable81 = 81,
IntVariable90 = 90,
IntVariable91 = 91,
IntVariable100 = 100,
IntVariable101 = 101,
IntVariable110 = 200,
IntVariable111 = 201
};
TestLongClass tc = new TestLongClass();
tc.IntVariable0 = 0;
tc.IntVariable1 = 1;
tc.IntVariable10 = 10;
tc.IntVariable11 = 11;
tc.IntVariable20 = 20;
tc.IntVariable21 = 21;
tc.IntVariable30 = 30;
tc.IntVariable31 = 31;
tc.IntVariable40 = 40;
tc.IntVariable41 = 41;
tc.IntVariable50 = 50;
tc.IntVariable51 = 51;
tc.IntVariable60 = 60;
tc.IntVariable61 = 61;
tc.IntVariable70 = 70;
tc.IntVariable71 = 71;
tc.IntVariable80 = 80;
tc.IntVariable81 = 81;
tc.IntVariable90 = 90;
tc.IntVariable91 = 91;
tc.IntVariable100 = 100;
tc.IntVariable101 = 101;
tc.IntVariable110 = 200;
tc.IntVariable111 = 201;
plc.WriteClass(tc, DB2);
Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
// Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
@@ -559,15 +551,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClassWithPrivateSetters tc = new TestClassWithPrivateSetters
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestClassWithPrivateSetters tc = new TestClassWithPrivateSetters();
tc.BitVariable00 = true;
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariable = -154.789;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -609,15 +599,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClass tc = new TestClass
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestClass tc = new TestClass();
tc.BitVariable00 = true;
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariable = -154.789;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -652,15 +640,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClass tc = new TestClass
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestClass tc = new TestClass();
tc.BitVariable00 = true;
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariable = -154.789;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
@@ -707,15 +693,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestStruct ts = new TestStruct
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestStruct ts = new TestStruct();
ts.BitVariable00 = true;
ts.BitVariable10 = true;
ts.DIntVariable = -100000;
ts.IntVariable = -15000;
ts.RealVariable = -154.789;
ts.DWordVariable = 850;
plc.WriteStruct(ts, DB2);
@@ -752,15 +736,13 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClass tc = new TestClass
{
BitVariable00 = true,
BitVariable10 = true,
DIntVariable = -100000,
IntVariable = -15000,
RealVariable = -154.789,
DWordVariable = 850
};
TestClass tc = new TestClass();
tc.BitVariable00 = true;
tc.BitVariable10 = true;
tc.DIntVariable = -100000;
tc.IntVariable = -15000;
tc.RealVariable = -154.789;
tc.DWordVariable = 850;
plc.WriteClass(tc, DB2);
int expectedReadBytes = Types.Class.GetClassSize(tc);
@@ -777,10 +759,8 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClassWithArrays tc = new TestClassWithArrays
{
Bool = true
};
TestClassWithArrays tc = new TestClassWithArrays();
tc.Bool = true;
tc.BoolValues[1] = true;
tc.Int = int.MinValue;
tc.Ints[0] = int.MinValue;
@@ -824,11 +804,9 @@ namespace S7.Net.UnitTest
{
Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
TestClassWithCustomType tc = new TestClassWithCustomType
{
Int = int.MinValue,
CustomType = new CustomType()
};
TestClassWithCustomType tc = new TestClassWithCustomType();
tc.Int = int.MinValue;
tc.CustomType = new CustomType();
tc.CustomType.Bools[1] = true;
tc.CustomTypes[0] = new CustomType();
tc.CustomTypes[1] = new CustomType();

View File

@@ -47,11 +47,11 @@ namespace S7.Net
/// Reads COTP TPDU (Transport protocol data unit) from the network stream
/// See: https://tools.ietf.org/html/rfc905
/// </summary>
/// <param name="socket">The socket to read from</param>
/// <param name="stream">The socket to read from</param>
/// <returns>COTP DPDU instance</returns>
public static TPDU Read(Socket socket)
public static TPDU Read(Stream stream)
{
var tpkt = TPKT.Read(socket);
var tpkt = TPKT.Read(stream);
if (tpkt.Length > 0) return new TPDU(tpkt);
return null;
}
@@ -60,11 +60,11 @@ namespace S7.Net
/// Reads COTP TPDU (Transport protocol data unit) from the network stream
/// See: https://tools.ietf.org/html/rfc905
/// </summary>
/// <param name="socket">The socket to read from</param>
/// <param name="stream">The socket to read from</param>
/// <returns>COTP DPDU instance</returns>
public static async Task<TPDU> ReadAsync(Socket socket)
public static async Task<TPDU> ReadAsync(Stream stream)
{
var tpkt = await TPKT.ReadAsync(socket);
var tpkt = await TPKT.ReadAsync(stream);
if (tpkt.Length > 0) return new TPDU(tpkt);
return null;
}
@@ -91,11 +91,11 @@ namespace S7.Net
/// Reads the full COTP TSDU (Transport service data unit)
/// See: https://tools.ietf.org/html/rfc905
/// </summary>
/// <param name="Socket">The stream to read from</param>
/// <param name="stream">The stream to read from</param>
/// <returns>Data in TSDU</returns>
public static byte[] Read(Socket Socket)
public static byte[] Read(Stream stream)
{
var segment = TPDU.Read(Socket);
var segment = TPDU.Read(stream);
if (segment == null) return null;
var output = new MemoryStream(segment.Data.Length);
@@ -103,7 +103,7 @@ namespace S7.Net
while (!segment.LastDataUnit)
{
segment = TPDU.Read(Socket);
segment = TPDU.Read(stream);
output.Write(segment.Data, (int)output.Position, segment.Data.Length);
}
return output.GetBuffer().Take((int)output.Position).ToArray();
@@ -113,11 +113,11 @@ namespace S7.Net
/// Reads the full COTP TSDU (Transport service data unit)
/// See: https://tools.ietf.org/html/rfc905
/// </summary>
/// <param name="socket">The stream to read from</param>
/// <param name="stream">The stream to read from</param>
/// <returns>Data in TSDU</returns>
public static async Task<byte[]> ReadAsync(Socket socket)
public static async Task<byte[]> ReadAsync(Stream stream)
{
var segment = await TPDU.ReadAsync(socket);
var segment = await TPDU.ReadAsync(stream);
if (segment == null) return null;
var output = new MemoryStream(segment.Data.Length);
@@ -125,7 +125,7 @@ namespace S7.Net
while (!segment.LastDataUnit)
{
segment = await TPDU.ReadAsync(socket);
segment = await TPDU.ReadAsync(stream);
output.Write(segment.Data, (int)output.Position, segment.Data.Length);
}
return output.GetBuffer().Take((int)output.Position).ToArray();

View File

@@ -17,10 +17,9 @@ namespace S7.Net
{
private const int CONNECTION_TIMED_OUT_ERROR_CODE = 10060;
/// <summary>
/// TCP Connection to device
/// </summary>
private Socket socket;
//TCP connection to device
private TcpClient tcpClient;
private NetworkStream stream;
/// <summary>
/// IP address of the PLC
@@ -70,11 +69,11 @@ namespace S7.Net
{
try
{
if (socket == null)
if (tcpClient == null)
return false;
//TODO: Actually check communication by sending an empty TPDU
return socket.Connected;
return tcpClient.Connected;
}
catch { return false; }
}
@@ -120,9 +119,9 @@ namespace S7.Net
/// </summary>
public void Close()
{
if (socket != null)
if (tcpClient != null)
{
if (socket.Connected) socket.Close();
if (tcpClient.Connected) tcpClient.Close();
}
}

View File

@@ -316,11 +316,6 @@ namespace S7.Net
}
}
/// <summary>
/// Get S7 Package for value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public byte[] GetPackage(object value)
{
switch (value.GetType().Name)

View File

@@ -1,6 +1,5 @@
using S7.Net.Types;
using System;
using System.Net;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
@@ -24,16 +23,16 @@ namespace S7.Net
{
await ConnectAsync();
await socket.SendAsync(GetCOPTConnectionRequest(CPU), 0, 22, SocketFlags.None);
var response = await COTP.TPDU.ReadAsync(socket);
await stream.WriteAsync(GetCOPTConnectionRequest(CPU), 0, 22);
var response = await COTP.TPDU.ReadAsync(stream);
if (response.PDUType != 0xd0) //Connect Confirm
{
throw new WrongNumberOfBytesException("Waiting for COTP connect confirm");
}
await socket.SendAsync(GetS7ConnectionSetup(), 0, 25, SocketFlags.None);
await stream.WriteAsync(GetS7ConnectionSetup(), 0, 25);
var s7data = await COTP.TSDU.ReadAsync(socket);
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[1] != 0x03) //Check for S7 Ack Data
{
throw new WrongNumberOfBytesException("Waiting for S7 connection setup");
@@ -43,9 +42,9 @@ namespace S7.Net
private async Task ConnectAsync()
{
IPEndPoint server = new IPEndPoint(IPAddress.Parse(IP), 102);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(server.Address, 102);
tcpClient = new TcpClient();
await tcpClient.ConnectAsync(IP, 102);
stream = tcpClient.GetStream();
}
/// <summary>
@@ -225,9 +224,9 @@ namespace S7.Net
package.Add(CreateReadDataRequestPackage(dataItem.DataType, dataItem.DB, dataItem.StartByteAdr, VarTypeToByteLength(dataItem.VarType, dataItem.Count)));
}
socket.Send(package.Array, package.Array.Length, SocketFlags.None);
await stream.WriteAsync(package.Array, 0, package.Array.Length);
var s7data = await COTP.TSDU.ReadAsync(socket);
var s7data = await COTP.TSDU.ReadAsync(stream); //TODO use Async
if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
@@ -400,9 +399,9 @@ namespace S7.Net
// package.Add(0x02); // datenart
package.Add(CreateReadDataRequestPackage(dataType, db, startByteAdr, count));
await socket.SendAsync(package.Array, 0, package.Array.Length, SocketFlags.None);
await stream.WriteAsync(package.Array, 0, package.Array.Length);
var s7data = await COTP.TSDU.ReadAsync(socket);
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
@@ -452,9 +451,9 @@ namespace S7.Net
// now join the header and the data
package.Add(value);
await socket.SendAsync(package.Array, 0, package.Array.Length, SocketFlags.None);
await stream.WriteAsync(package.Array, 0, package.Array.Length);
var s7data = await COTP.TSDU.ReadAsync(socket);
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff)
{
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
@@ -502,9 +501,9 @@ namespace S7.Net
// now join the header and the data
package.Add(value);
await socket.SendAsync(package.Array, 0, package.Array.Length, SocketFlags.None);
await stream.WriteAsync(package.Array, 0, package.Array.Length);
var s7data = await COTP.TSDU.ReadAsync(socket);
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());

View File

@@ -1,6 +1,5 @@
using S7.Net.Types;
using System;
using System.Net;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
@@ -26,16 +25,16 @@ namespace S7.Net
}
try
{
socket.Send(GetCOPTConnectionRequest(CPU), 0, 22, SocketFlags.None);
var response = COTP.TPDU.Read(socket);
stream.Write(GetCOPTConnectionRequest(CPU), 0, 22);
var response = COTP.TPDU.Read(stream);
if (response.PDUType != 0xd0) //Connect Confirm
{
throw new WrongNumberOfBytesException("Waiting for COTP connect confirm");
}
socket.Send(GetS7ConnectionSetup(), 0, 25, SocketFlags.None);
stream.Write(GetS7ConnectionSetup(), 0, 25);
var s7data = COTP.TSDU.Read(socket);
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[1] != 0x03) //Check for S7 Ack Data
{
throw new WrongNumberOfBytesException("Waiting for S7 connection setup");
@@ -55,10 +54,9 @@ namespace S7.Net
{
try
{
IPEndPoint server = new IPEndPoint(IPAddress.Parse(IP), 102);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(server);
return ErrorCode.NoError;
tcpClient = new TcpClient();
tcpClient.Connect(IP, 102);
stream = tcpClient.GetStream();
}
catch (SocketException sex)
{
@@ -269,13 +267,12 @@ namespace S7.Net
public ErrorCode WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
{
if (bitAdr < 0 || bitAdr > 7)
throw new Exception(string.Format("Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid", bitAdr));
throw new InvalidAddressException(string.Format("Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid", bitAdr));
ErrorCode lastError = WriteBitWithASingleRequest(dataType, db, startByteAdr, bitAdr, value);
if (lastError != ErrorCode.NoError)
{
return lastError;
}
return lastError; }
return ErrorCode.NoError;
}
@@ -351,9 +348,7 @@ namespace S7.Net
/// <returns>NoError if it was successful, or the error is specified</returns>
public ErrorCode WriteStruct(object structValue, int db, int startByteAdr = 0)
{
var bytes = Struct.ToBytes(structValue).ToList();
var errCode = WriteBytes(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
return errCode;
return WriteStructAsync(structValue, db, startByteAdr).Result;
}
/// <summary>
@@ -365,9 +360,7 @@ namespace S7.Net
/// <returns>NoError if it was successful, or the error is specified</returns>
public ErrorCode WriteClass(object classValue, int db, int startByteAdr = 0)
{
var bytes = Class.ToBytes(classValue).ToList();
var errCode = WriteBytes(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
return errCode;
return WriteClassAsync(classValue, db, startByteAdr).Result;
}
private byte[] ReadBytesWithSingleRequest(DataType dataType, int db, int startByteAdr, int count)
@@ -382,9 +375,9 @@ namespace S7.Net
// package.Add(0x02); // datenart
package.Add(CreateReadDataRequestPackage(dataType, db, startByteAdr, count));
socket.Send(package.Array, 0, package.Array.Length, SocketFlags.None);
stream.Write(package.Array, 0, package.Array.Length);
var s7data = COTP.TSDU.Read(socket);
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
@@ -436,9 +429,9 @@ namespace S7.Net
// now join the header and the data
package.Add(value);
socket.Send(package.Array, package.Array.Length, SocketFlags.None);
stream.Write(package.Array, 0, package.Array.Length);
var s7data = COTP.TSDU.Read(socket);
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff)
{
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
@@ -485,9 +478,9 @@ namespace S7.Net
// now join the header and the data
package.Add(value);
socket.Send(package.Array, package.Array.Length, SocketFlags.None);
stream.Write(package.Array, 0, package.Array.Length);
var s7data = COTP.TSDU.Read(socket);
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
@@ -509,6 +502,7 @@ namespace S7.Net
/// DataItems must not be more than 20 (protocol restriction) and bytes must not be more than 200 + 22 of header (protocol restriction).
/// </summary>
/// <param name="dataItems">List of dataitems that contains the list of variables that must be read. Maximum 20 dataitems are accepted.</param>
[Obsolete("Use ReadMultipleVarsAsync. Note: different function signature")]
public void ReadMultipleVars(List<DataItem> dataItems)
{
int cntBytes = dataItems.Sum(dataItem => VarTypeToByteLength(dataItem.VarType, dataItem.Count));
@@ -531,10 +525,10 @@ namespace S7.Net
{
package.Add(CreateReadDataRequestPackage(dataItem.DataType, dataItem.DB, dataItem.StartByteAdr, VarTypeToByteLength(dataItem.VarType, dataItem.Count)));
}
stream.Write(package.Array, 0, package.Array.Length);
socket.Send(package.Array, package.Array.Length, SocketFlags.None);
var s7data = COTP.TSDU.Read(socket);
var s7data = COTP.TSDU.Read(stream); //TODO use Async
if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());

View File

@@ -79,13 +79,12 @@
<Compile Include="Conversion.cs" />
<Compile Include="COTP.cs" />
<Compile Include="Enums.cs" />
<Compile Include="PLC.cs" />
<Compile Include="PLCAsynchronous.cs" />
<Compile Include="Plc.cs" />
<Compile Include="PlcAsynchronous.cs" />
<Compile Include="PLCExceptions.cs" />
<Compile Include="PLCHelpers.cs" />
<Compile Include="PLCSynchronous.cs" />
<Compile Include="PlcHelpers.cs" />
<Compile Include="PlcSynchronous.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SocketExtension.cs" />
<Compile Include="TPKT.cs" />
<Compile Include="Types\Bit.cs" />
<Compile Include="Types\Boolean.cs" />

View File

@@ -1,89 +0,0 @@
using System;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.CompilerServices;
namespace S7.Net
{
/// <summary>
/// Extensions to socket for using awaitable socket operations
/// </summary>
public static class SocketExtensions
{
/// <summary>
/// https://blogs.msdn.microsoft.com/pfxteam/2011/12/15/awaiting-socket-operations/
/// </summary>
/// <param name="socket"></param>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <param name="socketFlags"></param>
/// <returns></returns>
public static Task<int> ReceiveAsync(
this Socket socket, byte[] buffer, int offset, int size,
SocketFlags socketFlags)
{
var tcs = new TaskCompletionSource<int>(socket);
socket.BeginReceive(buffer, offset, size, socketFlags, iar =>
{
var t = (TaskCompletionSource<int>)iar.AsyncState;
var s = (Socket)t.Task.AsyncState;
try { t.TrySetResult(s.EndReceive(iar)); }
catch (Exception exc) { t.TrySetException(exc); }
}, tcs);
return tcs.Task;
}
/// <summary>
/// https://blogs.msdn.microsoft.com/pfxteam/2011/12/15/awaiting-socket-operations/
/// </summary>
/// <param name="socket"></param>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <param name="socketFlags"></param>
/// <returns></returns>
public static Task<int> SendAsync(
this Socket socket, byte[] buffer, int offset, int size,
SocketFlags socketFlags)
{
var tcs = new TaskCompletionSource<int>(socket);
socket.BeginSend(buffer, offset, size, socketFlags, iar =>
{
var t = (TaskCompletionSource<int>)iar.AsyncState;
var s = (Socket)t.Task.AsyncState;
try { t.TrySetResult(s.EndReceive(iar)); }
catch (Exception exc) { t.TrySetException(exc); }
}, tcs);
return tcs.Task;
}
/// <summary>
/// https://blogs.msdn.microsoft.com/pfxteam/2011/12/15/awaiting-socket-operations/
/// </summary>
/// <param name="socket"></param>
/// <param name="addresses"></param>
/// <param name="port"></param>
/// <returns></returns>
public static Task<int> ConnectAsync(this Socket socket, System.Net.IPAddress addresses, int port)
{
var tcs = new TaskCompletionSource<int>(socket);
socket.BeginConnect(addresses, port, iar =>
{
var t = (TaskCompletionSource<int>)iar.AsyncState;
var s = (Socket)t.Task.AsyncState;
try { t.TrySetResult(s.EndReceive(iar)); }
catch (Exception exc) { t.TrySetException(exc); }
}, tcs);
return tcs.Task;
}
}
}

View File

@@ -19,12 +19,12 @@ namespace S7.Net
/// <summary>
/// Reads a TPKT from the socket
/// </summary>
/// <param name="socket">The stream to read from</param>
/// <param name="stream">The stream to read from</param>
/// <returns>TPKT Instance</returns>
public static TPKT Read(Socket socket)
public static TPKT Read(Stream stream)
{
var buf = new byte[4];
int len = socket.Receive(buf, 0, 4, SocketFlags.None);
int len = stream.Read(buf, 0, 4);
if (len < 4) throw new TPKTInvalidException("TPKT is incomplete / invalid");
var pkt = new TPKT
{
@@ -35,7 +35,7 @@ namespace S7.Net
if (pkt.Length > 0)
{
pkt.Data = new byte[pkt.Length - 4];
len = socket.Receive(pkt.Data, 0, pkt.Length - 4, SocketFlags.None);
len = stream.Read(pkt.Data, 0, pkt.Length - 4);
if (len < pkt.Length - 4)
throw new TPKTInvalidException("TPKT is incomplete / invalid");
}
@@ -45,12 +45,12 @@ namespace S7.Net
/// <summary>
/// Reads a TPKT from the socket Async
/// </summary>
/// <param name="socket">The stream to read from</param>
/// <param name="stream">The stream to read from</param>
/// <returns>Task TPKT Instace</returns>
public static async Task<TPKT> ReadAsync(Socket socket)
public static async Task<TPKT> ReadAsync(Stream stream)
{
var buf = new byte[4];
int len = await socket.ReceiveAsync(buf, 0, 4, SocketFlags.None);
int len = await stream.ReadAsync(buf, 0, 4);
if (len < 4) throw new TPKTInvalidException("TPKT is incomplete / invalid");
var pkt = new TPKT
{
@@ -61,7 +61,7 @@ namespace S7.Net
if (pkt.Length > 0)
{
pkt.Data = new byte[pkt.Length - 4];
len = await socket.ReceiveAsync(pkt.Data, 0, pkt.Length - 4, SocketFlags.None);
len = await stream.ReadAsync(pkt.Data, 0, pkt.Length - 4);
if (len < pkt.Length - 4) throw new TPKTInvalidException("TPKT is incomplete / invalid");
}
return pkt;