Ich muss sagen, dass es beim Logging kaum was besseres gibt, als die Ausgabeumleitung der Konsole in eine Datei. Ob man Performance verschenkt weiß ich nicht, aber dafür habe ich eine Klasse die ich auch in anderen Projekten ohne Änderungen nutzen kann.
Und das beste ist: Das sind nur ~10 Zeilen Quelltext
--
mfg
Franknstein
Nur ein kleiner Punkt:
Exceptions sollten besser direkt am Entstehungsort behandelt werden. Exceptions fressen nämlich Ressourcen wie verrückt. Nimm als Begründung für das Using, dass man nicht das Dispose im Finally vergessen kann oder der wichtige Code nicht so weit auseinandergezogen wird...
Das mit dem Timeout wird meines Erachtens so nicht funktionieren, da Socket.Receive den Thread so lange blockt, bis wirklich Daten empfangen wurden.
Es gibt zwei Alternativen:
a) Du liest in der MSDN nach, was die cSocket.RecieveTimeOut bewirkt setzt, falls das klappt, diese Zeit
b) Es müsste ein Feld geben, das Available oder so heißt. Wenn das größer 0 ist, sind Daten zum Empfangen vorhanden. Wenn du deinen Code so erweiterst, dass du vor dem Empfangen prüft, ob überhaupt was da ist, sollte dein Code so gehen.
z.B. kann man ja auf seinem eigenen Rechner einen WebServer einrichten. Damit aber auch noch normal surfen kann, und das nicht in Konflikt mit Port 80 setzen will, legt man konventionsmäßig den lokalen WebServer auf Port 8080.
In meiner grenzenlose Unwissehnheit behaupte ich, dass der Browser vermutlich nicht den Port 80 benutzt, wenn er eine Verbindung zu einem Webserver aufbaut. Der Browser sollte automatisch vom Betriebssystem einen freien Port zugewiesen bekommen. Er braucht ja auch keinen fest definierten Port, da der Browser nicht darauf angewiesen ist, auf Verbindungen von außen zu warten. Der Browser baut ja eine Verbindung zu einem Webserver auf(der Webserver horcht im Normalfall auf Port 80), schickt die Anfrage los, bekommt eine Antwort und schließt die Verbindung wieder.
Oder bin ich völlig unwissend und auf dem Holzweg?
Ich glaube ich kennen den Fehler:
x = cos(w + fi) * r
y = sin(w + fi) *r
Soweit ich das sehen kann, ist bei deiner Formel hier alles im Sinus erstens konstant (und zweitens nicht einheitenfrei). Daher bekommst du immer den selben Punkt. Wenn du die Winkelgeschwinigkeit einheitenfrei machst(also mit t multiplizierst) sollte es gehen. Du musst halt bei den Schleifendurchläufen die verstrichene Zeit messen.
Edit:
Übrigens würde ich nicht mit der Kanone auf die Spatzen schießen und die Kreisbahn mit
r² = x ² + y² beschreiben.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace TcpTest
{
class MyTcpClient : TcpClient
{
public Socket GetSocket()
{
return base.Client;
}
}
}
Allerdings bin ich mir nicht sicher, ob das so funktioniert, da ich es nicht testen kann.
Anstatt einer neuen Funktion könnte man auch die Client-Property überschreiben(Falls ich lüge, sagt es mir nur)?
Bearbeitung:
Ich habe noch eben den Namespace geändert...
Kann es sein, dass es TcpClient.Client nur im Framework 2.0 gibt? Im SharpDevelope 1.1 gibts das nämlich nicht.
Stimmt nicht ganz, diese Eigenschaft ist nämlich nur nicht öffentlich wie in V2. Aber es existiert intern eine gleichnamige Socket-Variable. Das heißt, du musst einfach eine Klasse von der TCPClient-Klasse erben lassen, und diese Eigenschaft veröffentlichen. So kannst du dann auch darauf zugreifen. Ich denke, es müsste auch irgendwie per Reflection hinzuzimmern sein, aber das ist keine angemessene Lösung.
Ich habe noch nie ein Spiel programmiert, aber Spiele haben eh immer eine Endlosschleife, in welcher alle Aktionen abgearbeitet werden. Daher ist es auch kein Problem, da auch noch einen Socket abzufragen, ob neue Daten da sind... Und da ein Spiel eigentlich das selbe Verhalten wie eine Endlosschleife hat, welche nirgends pausiert, braucht man auch nirgends das Programm schlafen zu lassen.
Das anbinden fast jeder Datenbank funktioniert zimlich ähnlich. Dies kommt, weil von Microsoft Vorgaben existieren, was ein Datenbankclient zu können hat, und diese auch eingehalten werden. (Diese Aussage ist evtl. nicht allgemeingültig...)
Daher sind als gute Schlagwörter MySQLConnection, MySQLCommand und MySQLDataReader zu nennen. Falls du gute Schlagwörter für die andere Datenbank suchst, lass doch einfach das MySQL weg und setze stattdessen ein Teil des anderen Datenbanknamens ein.
Ob oder wie die Datenbanken direkt von Visual Studio zu verwenden sind, weiß ich nicht, weil ich das nie mache.
Übrigens kann man sich einen Command in deinem Quelltext evtl. sogar sparen, da für jede Verbindung das Ergebnis des letzten Einfügevorgangs in der Variablen @Identity oder der Funktion Last_Insert_Id() gespeichert wird. Daher funktioniert das Auswählen dieser Variablen oder Funktion auch ohne den Namen einer Tabelle anzugeben. Jedenfalls kann man diese Variablen auch noch im nächsten Kommando weiterverwenden....
Bearbeitet: Ich habe ca. 57 Rechtschreib- Grammatikschreibfehler entfernt.....
Je nach dem welche Funktionen beim MS Sql benutzet wurden, wirst du viel Vergnügen haben...
Je nach dem, wie die Daten aus der Datenbank kommen, genügt es, den Klassennamen zu ändern. Wenn du Pech hast, musst du aber einiges neu machen. Es kommt darauf an, welche Funktionen vom SqlServer verwendet wurden und ob vorher schon jemand dran gedacht hat, das Programm evtl später auf eine neue Datenbank zu portieren.
Das mit den eckigen Klammern funktioniert. Ich habe es zwar noch nie gesehen, aber ich werde mir auf alle Fälle merken, dass man die auch benutzen kann.
Sind sich die Tabellenstrukturen der unterschiedlichen Tabellen sehr ähnlich, wenn aus allen Tabellen das gleiche ausgewählt wird? Könntest du dann nicht eine ,,große`` Tabelle verwenden und andere Unterscheidungsmerkmale einbauen?
Was ist genau das Problem daran, die Addresse zu speichern? Muss man die überhaupt so lange speichern?
Du könnstest doch auf die Message mit der IP vom Server warten und dannach direkt dich zu dem Server verbinden? Dann brauchst du die Addresse nur in Variablen zu speichern....
Der DataReader kann einem doch auch gut die Schemadaten zurückgeben. Der Datareader hat eine Funktion GetSchemaTable(). Damit bekommt man das Schema in einem DataSet zurück.
Ich würde uneingeschränkt zum DataReader raten, weil man die Verbindung selbst im Griff hat. So bekommt man u.U. keine Probleme mit sich als störend erweisenden Eingenschaften des DataSet. Leider kann immer nur ein Datareader pro Verbindung gleichzeitig auf Daten zugreifen. Aber das ist kein allzugroßes Problem.
Hierfür gibt es evtl. eine schöne und einfache Lösung, da die Möglichkeit B einfach nur abgrundtief böse ist. Man muss nämlich immer vermeiden, Daten mehrfach in der Datenbank abzulegen. Daher bietet sich eine objektrelationale Datenbank an. Eine solche ist beispielsweise die Postgresql-Datenbank. Ich habe hier sogar einen Link für dich, der dir vielleicht weiterhilft: http://www.postgresql.org/docs/8.1/interactive/sql-createtable.html
Stichwort INHERITS
Hallo,
Ich nutze den SqlServer 2005 ebenfalls für ein Projekt. Eigentlich wollte ich ja die PostGresql-Datenbank verwenden, allerdings wurde ich davon überzeugt, dass es besser sei, den SQLServer zu verwenden.
Die Installation des SQLServers war eine leider sehr zeitaufwändig,was ungewöhnlich für ein Microsoftprodukt ist. Allerdings bin ich positiv vom SQLServer überrascht, seit er läuft. Das einizge was mich geärgert hat, war das Microsoft Administrationswerkzeug was irgentwie nicht so wollte wie ich und andauernd abgestürzt ist. Daher nehme ich jetzt die kostenlose Version von SQL Manager 2005. Seitdem ich diesen Schritt gegangen bin, habe ich mich auch nicht mehr über den SQLSerer aufgeregt. Die Schnittstelle nach C# ist wie gewohnt sehr gut. Über die Geschwindigkeit kann ich noch keine Aussagen treffen. Der Funktionsumfang ist einfach riesig. Was ich allerdings noch nie gemacht habe, aber mal dringen probieren müsste ist, Assemblys als Stored Procedures einzubinden.
Alternativen sind wie erwähnt der PostgreSql-Server. Dieser hat den Vorteil, dass sich auch mit anderen Sprachen als T-SQL Stored Procedures erzeugen lassen. Außerdem treibt einen die Installation nicht in den Wahnsinn. Ich eigentlich nie Probleme mit dem Postgres. Vom Funktionsumfang ist diese Datenbank vielleicht noch etwas komplexer, da sie eine objektrelationale Datenbank darstellt.
MySQL 5?
Ist das eine Alternative? Habe seit Version 4 nichts mehr mit Mysql gemacht und damals war die Datenbank aufgrund fehlender Funktionen fast nutzlos. Aber das soll ja angeblich mit der 5. Version besser geworden sein. Ich werde sie dennoch nicht mehr so bald benutzen.
Also, die Funktion die per Event aufgerufen wurde überprüft, ob sie sich invoken muss. Wenn nein gehts ganz normal weiter. Wenn ein Invoke durchgeführt werden muss, dann wird die Funktion einfach mit den selbigen Parametern aufgerufen. Aber vom richtigen Thread aus.
Wenn du dein Programm als Brücke zwischen zwei anderen verwendest gehe ich davon aus, dass du keinen Fehler im Programmablauf hast, sondern dass einfach was wichtiges dem anderen Programm fehlt, sodass das andere Programm die Verbindung wieder beendet.
Wie ich das sehe, gehst du ja stur die Packete zwischen den beiden Applikationen routen und greifst sie halt noch ab.
Vielleicht müsstest du das erstmal nur mit einem Programm machen. Also so, dass nur ein Programm zu deinem Programm verbinden kann. Später kannst du ja das andere noch dazu bauen. Wichtig ist, dass du deinen Quelltext erstmal von sinnlosem Zeug fern halten musst. So kannst du nämlich Fehler ausschließen.
Vielleicht machst du erstmal nur ein einfaches Konsolenprogramm, das nichts anderes tut, als die Verbindung zu brücken.
Auf deine ersten beiden Fragen habe ich keine Lösung. ABer ich kann dir eventuell weiterhelfen den Fehler selbst zu finden:
a) Mach bitte aus der Funktion eine(mehrere) Klassen. Oder zumindest mehrere Funktionen. Es ist nämlich als Außenstehender nicht leicht, bei dem Code durchzublicken.
b) Warum verwendest du zwei Verbindungen? Dient dein Programm nur als Brücke zu einem weiteren Programm oder baust du zwei Verbindungen auf damit du auf einer sendest und auf der anderen empfängst? Hast du eigentlich den selben Code auch auf der Gegenseite laufen?
Aber bei den Events kann ich dir helfen.
Du fügst in der Klasse über deiner Funktion in etwa sowas ein:
public event EventHandler OnMessageArrive;
Und dann in deiner Funktion an der Stelle, an der du z.B. eine neue Meldung empfangen hast:
if(this.OnMessageArrive != null)
this.OnMessageArrive(message, new EventArgs());
Das ist die einfachste Lösung einen Event zu realisieren. Aber auch die unschönste. Du missbrauchst das Feld sender quasi um deine eigene Meldung zu übertragen. Falls du das so nicht machen willst, musst du dir eine Klasse und ein Delegate definieren. Dann kannst du so viele Daten mit einem Event übertragen, wie du möchtest.
Hm, ein selbst verwaltendes Netzwerk(nenne ich in meiner Naivität einfach mal so) ist vermutlich nicht so leicht. Fang erstmal ,,klein" an und entwickle eine getrennte Server-Anwendung.
Dannach baust du eine Funktion ein, mit der du automatisch die Maschine mit dem Server finden kannst(also ohne die IP des PCs mit dem Server zu kennen).
Wenn das geschafft ist, kannst du ja wichtige Teile des Servers im neuen Projekt weiterverwenden.
Natürlich kannst du das oben auch überspringen und gleich sowas machen:
Die Applikation wartet auf dem Port x auf eine neue Verbindung. Weiterhin geht sie alle alle IPs im Netzwerk durch auf der Suche nach anderen Applikationen.
Falls dann mal eine andere Instanz gefunden wurde, fangen die kleinen Problemchen an. Hier gibt es nämlich mehrere Lösungen:
a) Alle Instanzen des Chatprogramms wissen immer genau, welcher Chatter an welcher Maschiene ist und jede Instanz weiß genau, wann sie was zu tun hat. Alle Instanzen haben die selben Rechte.
b) Eine Instanz wird zum Server bestimmt(dazu rate ich). Aber es macht bestimmt einen riesigen Aufwand das ganze zu testen und alle Fehler rauszubauen. Man muss hier halt verdammt aufpassen, dass rechtzeitig die Erbfolge des Servers bestimmt wird. Es kann ja immer mal passieren, dass ein PC vom Netz getrennt wird, abstürzt oder sowas.
Also, wie man wohl lesen kann, habe ich sowas noch nie gemacht. Aber das sind so im groben die Ideen die mir auf die Schnelle dazu eingefallen sind.
Hm, so blöd ist die Frage nicht. Du kannst ja auch einen TcpClient von einem TCPListener bekommen.
Jedenfalls hat man damit recht große Probleme, wenn man nicht VS2005 nimmt(Da bietet die Klasse endlich direkt Zugriff auf den Socket...)
Es gibt drei Möglichkeiten:
a) Eine neue Klasse erzeugen die vom TCPClient erbt und die Property Server öffentlich zugänglich macht.
b) Auf die Property Server per Reflection zugreifen(habe ich mal machen müssen)
c) Gleich Sockets verwenden
Mein interessantestes Projekt war die Mitarbeit an einem Kommunikationsstack für ein zukünftigen Fahrzeugbus. Hardwarebedingt natürlich nicht mit .Net möglich, dafür hab ich gelernt C als Sprache noch mehr zu hassen smile Aber es ist einfach faszinierend in den embedded Bereich reinzuschnuppern. Hardware mit der Seriennummer 1 und 2 vor sich zu haben wo keiner weiß ob die wirklich funktioniert großes Grinsen , nur die Möglichkeit für 5 Hardwarebreakpoints beim Debuggen um dann festzustellen das man eh net geschickt debuggen kann weil die IRS's alles durcheinanderhaun. Und das ganze wird in Zukunft auch noch auf unseren Straßen rumfahren smile Neben C# ist das echt eins von meinen Lieblingsgebieten.
Sowas ist für mich einer der Gründe Elektro- und Informationstechnik studieren zu wollen...