2008-11-03 10 views
5

Ich habe eine ungewöhnliche Situation: Ich verwende ein Linux-System in einer eingebetteten Situation (Intel-Box, die derzeit einen Kernel 2.6.20 verwendet) kommunizieren mit einem eingebetteten System, das eine teilweise unterbrochene TCP-Implementierung aufweist. So weit ich das jetzt sagen kann, erwarten sie, dass jede Nachricht von uns in einem separaten Ethernet-Frame kommt! Sie scheinen Probleme zu haben, wenn Nachrichten über Ethernet-Frames aufgeteilt werden.Ich brauche eine TCP-Option (ioctl), um Daten sofort zu senden

Wir sind im lokalen Netzwerk mit dem Gerät, und es gibt keine Router zwischen uns (nur ein Schalter).

Wir versuchen natürlich, sie zu zwingen, ihr System zu reparieren, aber das kann nicht machbar sein.

Ich habe bereits TCP_NODELAY auf meinen Sockets (ich verbinde mich mit ihnen), aber das hilft nur, wenn ich nicht versuche, mehr als eine Nachricht auf einmal zu senden. Wenn ich mehrere ausgehende Nachrichten hintereinander habe, neigen diese Nachrichten dazu, in einem oder zwei Ethernet-Frames zu enden, was Probleme auf dem anderen System verursacht.

Ich kann das Problem im Allgemeinen vermeiden, indem ich einen Timer verwende, um zu vermeiden, dass Nachrichten zu nahe zusammen gesendet werden, aber das begrenzt offensichtlich unseren Durchsatz. Außerdem, wenn ich die Zeit zu niedrig stelle, riskiere ich eine Netzwerküberlastung, die Paketübertragungen hochhält und schließlich erlaubt, dass mehr als eine meiner Nachrichten in demselben Paket gespeichert werden.

Gibt es eine Möglichkeit, dass ich sagen kann, ob der Fahrer Daten in der Warteschlange hat oder nicht? Gibt es eine Möglichkeit, den Treiber dazu zu zwingen, unabhängige Schreibaufrufe in unabhängigen Transportschichtpaketen zu senden? Ich habe die Manpages von Socket (7) und TCP (7) durchgesehen und habe nichts gefunden. Vielleicht weiß ich nicht, wonach ich suche.

Offensichtlich würde UDP ein Ausweg sein, aber ich denke nicht, dass wir das andere Ende ändern können, etwas an dieser Stelle.

Jede Hilfe sehr geschätzt.

Antwort

7

IIUC, sollte die Option TCP_NODELAY alle Pakete bündig machen (d. H. Tcp.c implementiert die Einstellung von NODELAY mit einem Aufruf von tcp_push_pending_frames). Wenn Sie also die Socket-Option nach jedem Sendeanruf einstellen, sollten Sie bekommen, was Sie wollen.

1

Vielleicht setzen Sie TCP_NODELAY und stellen Sie Ihre MTU niedrig genug, so dass es höchstens 1 Nachricht pro Frame geben würde? Oh, und fügen Sie "Dont-Fragment" -Flag auf ausgehenden Pakete

+0

Schöne Idee. Da die Nachrichten keine einheitliche Größe haben, kann ich leider keine MTU auswählen, die in diesem Fall eine Nachricht pro Bild sicherstellt. –

0

Haben Sie versucht, einen neuen Socket für jede Nachricht zu öffnen und es sofort zu schließen? Der Overhead kann widerlich sein, aber dies sollte Ihre Nachrichten abgrenzen.

+0

Leider würde dies am anderen Ende mehr Probleme verursachen als die fragmentierten Nachrichten, daher wird es in diesem Fall nicht funktionieren. –

0

Im schlimmsten Fall könnten Sie eine Stufe tiefer gehen (rohe Sockets), wo Sie die gesendeten Pakete besser kontrollieren können, aber dann müssten Sie sich mit TCP beschäftigen.

-1

Vielleicht versuchen Sie können den TCP-Stack in Low-Latency-Modus versetzen:

echo 1 > /proc/sys/net/ipv4/tcp_low_latency 

Das begünstigen sollte Pakete so schnell wie möglich über die Kombination von Daten zu emittieren. Lesen Sie den Mann auf TCP (7) für weitere Informationen.

+0

Gemessen am Code im Linux-Kernel (net/ipv4/tcp.c) beeinflusst das tcp_low_latency-Flag nur das Lesen von Daten aus dem TCP-Stack in den Anwendungspuffer. – Alexander

+0

Alexander hat Recht –

2

Sie können ein Problem nur umgehen, wenn Sie sich sicher sind, was das Problem ist.

Wenn sie den Anfänger Fehler gemacht haben anzunehmen, dass recv() genau eine Nachricht empfängt, dann sehe ich keinen Weg, es vollständig zu lösen.Das Senden von nur einer Nachricht pro Ethernet-Rahmen ist eine Sache, aber wenn mehrere Ethernet-Rahmen ankommen, bevor der Empfänger recv() anruft, werden immer noch mehrere Nachrichten in einem Anruf empfangen.

Netzwerkstauung macht es praktisch unmöglich, dies zu verhindern (während ein angemessener Durchsatz aufrechterhalten wird), selbst wenn sie Ihnen sagen können, wie oft sie recv() aufrufen.

+1

Leider läuft das Gerät am anderen Ende keinen normalen TCP-Stack, soweit ich das beurteilen kann. Es ist ein kleines Embedded-Gerät, das irgendwann auf einer Ethernet-Platine ihres eigenen Designs installiert wurde. Von dem Verhalten, das ich vermute, stöbern sie in den Ethernet-Frames herum. –

Verwandte Themen