Forums Neueste Beiträge
 

Visual Studio 2008 - Socket C# - Nachfrage

04/05/2009 - 19:24 von Martin Greul | Report spam
Hallo,

wer ist bereit mir nochmals konkret zu helfen.
DANKE im voraus.

http://www1.minpic.de/bild_anzeigen...2&ende
http://www1.minpic.de/bild_anzeigen...6&ende

3 Probleme
- Socket immer neu aufbauen, ok?
- Dateilànge, die ersten 4 Bytes
+ Senden
+ Empfangen
http://www1.minpic.de/bild_anzeigen...6&ende
http://www1.minpic.de/bild_anzeigen...8&ende
- Timeout, lesen bis alles empfangen

Ich habe jetzt den Vorschlag von Frank implementiert.
http://www.codeplanet.eu/tutorials/...ml?start=1
http://dzaebel.net/TcpClientServer.htm
Für mich ist auch die Timeout Geschichte wichtig, also synchron ausreichend.

Frage:
Ist das ein Problem, wenn für jedes Telegramm die Socketverbindung
geöffnet wird?
Ca. 5 bis 10 Telegramme pro Minute.

Wie kann ich das mit der Lànge einfacher lösen?
Die erste 4 Bytes sind mit einer 'eigenartigen' Làngenkodierung versehen.
Geht es auch einfacher.
Das unsafe habe ich aus dem Internet recherchiert.
siehe Dateien im Anhang.

Jetzt hole ich Pakete zu je 4096 ab und baue das Telegramm zusammen.
Was nicht geht. Wie es beschrieben ist.
Ich muss es so machen, sprich
do
{
bytes = sock.Receive(bytesReceived, bytesReceived.Length,
SocketFlags.None);
// konvertiere die Byte Daten in einen string

page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);

myCompleteMessage.AppendFormat("{0}",
Encoding.ASCII.GetString(bytesReceived, 0, bytes));
System.Array.Copy(bytesReceived, 0, arrResult, nCount, bytes);
nCount += bytes;

if (bytes != bytesReceived.Length)
break;
}
while (bytes > 0);
bytes ist nie 0
Nur wenn ich es so mache, geht es.
if (bytes != bytesReceived.Length)
break;


Grüße Martin

Der komplette Code im Anhang

// Initialisiert die Socketverbindung und gibt diese zurück
private static Socket Alternative_ConnectSocket(string server,
int port)
{
Socket sock = null;
IPHostEntry hostEntry = null;

hostEntry = Dns.GetHostEntry(server);

// Nutze die Eigenschaft AddressFamily von IPEndPoint um Konflikte
// zwischen IPv4 und IPv6zu vermeiden. Iteriere dazu durch die
Adressliste.
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipo = new IPEndPoint(address, port);
Socket tempSocket = new Socket(ipo.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);

tempSocket.Connect(ipo);

if (tempSocket.Connected)
{
sock = tempSocket;
break;
}
else
{
continue;
}
}
return sock;
}

// Die Methode sendet eine HTTP GET 1.1 Anfrage an den Server und
// empfàngt die Daten
unsafe private static string Alternative_SocketSendReceive(string
server, int port, string strReq, bool bResponse)
{
Socket sock = null;
// Die zu sendenden Daten
string request = "GET / HTTP/1.1Host: " + server +
"Connection: Close";

request = strReq;

StringBuilder myCompleteMessage;
myCompleteMessage = new StringBuilder();


// **** Kundenspezifisch
Byte[] arrReq = System.Text.Encoding.UTF8.GetBytes(strReq);
int nLength = arrReq.Length;
// ** Spezifikation --> Größe des Nachrichtenkopfs (4 Byte)
Byte[] bytesSent = new byte[nLength + 4];
fixed (byte* p = &bytesSent[0])
{
int* pi = (int*)p;
*pi = System.Net.IPAddress.NetworkToHostOrder(nLength + 4);
}
// ** Copy Spezifikation --> Array sourceArray, int sourceIndex,
Array destinationArray, int destinationIndex, int length
System.Array.Copy(arrReq, 0, bytesSent, 4, nLength);
// ****

// Kodiere den string in Bytes
//Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
// Lege ein Byte Array an für die zu emfangenden Daten
Byte[] bytesReceived = new Byte[4096];

Byte[] arrResult = new Byte[64 * 1024];


// Instanziere ein gültiges Socket Objekt mit den übergebenen
Argumenten
sock = Alternative_ConnectSocket(server, port);
if (sock == null)
return ("Connection failed!");
// Sende den HTTP-Request
sock.Send(bytesSent, bytesSent.Length, SocketFlags.None);
int bytes = 0;
int nCount = 0;
string page = ""; // = "Default HTML page on " + server + ":";

// Empfange die Daten und konvertiere sie

sock.ReceiveTimeout = 2500;

try
{
do
{
bytes = sock.Receive(bytesReceived, bytesReceived.Length,
SocketFlags.None);
// konvertiere die Byte Daten in einen string

page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);

myCompleteMessage.AppendFormat("{0}",
Encoding.ASCII.GetString(bytesReceived, 0, bytes));
System.Array.Copy(bytesReceived, 0, arrResult, nCount, bytes);
nCount += bytes;

if (bytes != bytesReceived.Length)
break;
}
while (bytes > 0);
}
catch (SocketException e)
{
System.Diagnostics.Debug.Assert(false, e.Message);
System.Diagnostics.Debug.WriteLine("SocketException: {0}",
e.Message);
return "Error Tmeout";
}

string response = "";
if (bResponse == true)
{
//sResp = System.Text.Encoding.ASCII.GetString(page, 4,
page.Length - 4);
response = System.Text.Encoding.ASCII.GetString(arrResult, 4,
arrResult.Length - 4);
}

// Unterbinde alle weiteren Send() und Receive() Aktivitàten am
Socket
sock.Shutdown(SocketShutdown.Both);
sock.Close();
return response;
}
 

Lesen sie die antworten

#1 Günter Prossliner
05/05/2009 - 09:40 | Warnen spam
Hallo Martin!

3 Probleme
- Socket immer neu aufbauen, ok?



Ja. Wir spechen ja nicht von tausenden Sockets / Sekunde (wobei das
protokollbedingt auch oft nicht anders möglich ist).

- Dateilànge, die ersten 4 Bytes



Ja.

+ Senden
+ Empfangen
http://www1.minpic.de/bild_anzeigen...6&ende
http://www1.minpic.de/bild_anzeigen...8&ende
- Timeout, lesen bis alles empfangen



Kannst Du das nicht einfach als Text reinkopieren in Zukunft?

ASCII? Bekommst Du keine Sonderzeichen?

Für mich ist auch die Timeout Geschichte wichtig, also synchron
ausreichend.



Ist in sehr vielen Fàllen so.

Ist das ein Problem, wenn für jedes Telegramm die Socketverbindung
geöffnet wird?
Ca. 5 bis 10 Telegramme pro Minute.



Wenn es das Protokoll unterstützt kann der Socket auch offen bleiben (z.b.
keep alive bei HTTP). Jemand muss dann halt bereits ein "Read" für den
nàchsten Request absetzen.

Aus der Sicht des Resourcenverbrauchs würde ich mir da aber keine Gedanken
machen. Der Performancegewinn wird in Summe kaum messbar sein. Also durchaus
ok.

Wie kann ich das mit der Lànge einfacher lösen?
Die erste 4 Bytes sind mit einer 'eigenartigen' Làngenkodierung
versehen.



Die "eigenarteige" Làngenkodierung ist die Network Byte Order. Diese ist (im
Gegensatz zu der Windows Byteorder - und übrigens auchder nativen Byte-Order
vieler CPUs) Big-Endian und nicht Little Endian.

siehe:

[Byte-Reihenfolge]
http://de.wikipedia.org/wiki/Byte-Reihenfolge

Geht es auch einfacher.
Das unsafe habe ich aus dem Internet recherchiert.



Es ist schon "sehr komplex" so. Em Endeffekt kannst Du auch einfach die
Bytes selbst umdrehen (ganz ohne unmanaged Code):

byte[] tempBytes = new byte[4];
stream.Read(tempBytes, 4, 0); // hier auch return-value überprüfen (oder
BufferedStream verwenden)
for(int i = 0; i < 3; i++) {
tempBytes[i] = responseLengthBytes[3 - i];
}
int length = BitConverter.ToInt32(tempBytes, 0);



// Die Methode sendet eine HTTP GET 1.1 Anfrage an den Server und
// empfàngt die Daten



Warum nun auf einmal HTTP???

Um Dir Daten über HTTP zu holen verwendest Du am besten den WebClient bzw.
den HttpWebRequest.

HTTP hat aber eine eigene Spezifikation für das Kodieren von Làngen!


mfg GP

Ähnliche fragen