Stránka 1 z 1
C# - TCP
Napsal: ned 14. srp 2011, 10:14
od gorilino
Dobrý den ,
vytvořil jsem si klienta a server pro TCP komunikaci , a mam problem se zamrzanim obou aplikaci kdyz zahajuji spojeni ... Dále bych se chtěl zeptat jak mám na serveru vypsat obsah NetworkStreamu ... jak jej prevest do textoveho retezce . A poslední dotaz ... kdyz zmacknu tlacitko pro zapnuti serveru tak chci aby ihned vypsal do richtextboxu ze ceka na pripojeni klienta ... on se mi ten text ze ceka na pripojeni objevi az kdyz v klientske aplikaci zmacknu tlacitko pro pripojeni k serveru a pak obe aplikace zamrznou ....
Děkuji
Kod Klient:
private void button1_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpklient = new TcpClient();
tcpklient.Connect("127.0.0.1", 2000);
if (tcpklient.Connected)
{
richTextBox1.Text = "Pripojen k serveru";
NetworkStream ns = tcpklient.GetStream();
while (ns.CanWrite)
{
a:
textBox1.Text = "Zadejte co chcete odeslat";
byte[] data = Encoding.ASCII.GetBytes(textBox1.Text);
ns.Write(data, 0, data.Length);
goto a;
}
}
}
catch (Exception vyjimka)
{
MessageBox.Show(vyjimka.Message);
}
}
Kod Server:
private void button1_Click(object sender, EventArgs e)
{
try
{
TcpListener tcpposlouchac = new TcpListener(2000);
tcpposlouchac.Start();
while (true)
{
richTextBox1.Text="Cekam na pripojeni klienta";
TcpClient tcpklient = tcpposlouchac.AcceptTcpClient();
if (tcpklient.Connected)
{
richTextBox1.Text += "\n Klient pripojen";
NetworkStream NS = tcpklient.GetStream();
byte[] zprava = new byte[1024];
// ZDe bych potreboval vypsat do richtextboxu obsah Network Streamu
}
}
}
catch (Exception chyba)
{
MessageBox.Show(chyba.Message);
}
}
Re: C# - TCP
Napsal: ned 14. srp 2011, 11:10
od OndraSter
Musíš použít asynchronní volání těch socketových funkcí.
Re: C# - TCP
Napsal: ned 14. srp 2011, 11:13
od Maranov
Kód: Vybrat vše
a:
textBox1.Text = "Zadejte co chcete odeslat";
byte[] data = Encoding.ASCII.GetBytes(textBox1.Text);
ns.Write(data, 0, data.Length);
goto a;
Co se sakra tohle?

a) goto patří do Assembleru, ne do vyšších jazyků; nepoužívej
b) neustále ti to cyklí a odesílá "Zadejte co chcete odeslat"; to bude asi ten problém
Máš tam pár nepotřebných věcí, co se týče zaseknutí GUI, neškodilo by komunikaci pustit v odděleném WorkerThread. Server kvůli tomu není konkurentní, takže více klientů neobslouží, možná má problém i s oním jedním klientem, který odesílá moc rychle.
Na MSDN jsou pěkné ukázky, ze kterých můžeš vyjít a obsahují i opačnou konverzi pro odeslaný řetězec:
http://msdn.microsoft.com/en-us/library ... aspx#Y2160
http://msdn.microsoft.com/en-us/library ... S.71).aspx
Re: C# - TCP
Napsal: ned 14. srp 2011, 11:14
od gorilino

ooops ... bohuzel nemam ani paru co je asynchronni volani ... mohl bys mi to nejak vysvetlit a uvest priklad? jeste se chci zeptat proc jsou v nekterych aplikacich pouzivany objekty Sockets a v nekterych TcpClient a TcpListener? co je vyhodnejsi? to goto sem tam dal prave kvuli zacykleni ... ja vim ze se to nema pouzivat ... ja to tam jen prdnul na odzkouseni
Re: C# - TCP
Napsal: ned 14. srp 2011, 11:25
od OndraSter
Aha, tak samotný TcpClient zřejmě nemá asynchronní verzi (asynchronní = vytvoří si další thread pro připojování, pro přijímání dat atd). Tu má jenom Socket s BeginConnect, BeginReceive, BeginSend atd.
Anebo, jak Maranov říká, použít BackgroundWorker.
Re: C# - TCP
Napsal: ned 14. srp 2011, 11:40
od gorilino
V jednom ukazkovem kodu bylo toto .... nechapu to pouziti celociselne promenne b ... dokazete mi nekdo vysvetlit?
NetworkStream NS = tcpklient.GetStream();
StringBuilder SB = new StringBuilder();
byte[] zprava = new byte[1024];
int b = 0;
do
{
b = NS.Read(zprava, 0, zprava.Length);
SB.AppendFormat(Encoding.ASCII.GetString(zprava, 0, b));
}
while (NS.DataAvailable);
richTextBox1.Text = SB;
Re: C# - TCP
Napsal: ned 14. srp 2011, 11:52
od Maranov
Udává to skutečnou délku té přečtené zprávy. Buffer má 1024B, zpravidla ale nemusí být vždy naplněný celý, proto z něj čteš jen tu krátkou zprávu.
BTW používej tag
[/code], fórum ničí odsazení.
Re: C# - TCP
Napsal: ned 14. srp 2011, 12:08
od gorilino
a kdyz to presahne velikost 1024 tak to hodi chybu? nejaky overflow exception? a ten buffer ... pokud to dobre chapu slouzi pro ukladani prenesenych dat? jako ze se mi odesilaji nejaka data a ty se pekne byte po bytu ukladaji do bufferu ? a kdyz posle dalsi zpravu tak se ten buffer vymaze nebo se do nej ukladaji data ty zpravy za sebou?

tomuhle moc nerozumim tak mozna mluvim blbosti
Re: C# - TCP
Napsal: ned 14. srp 2011, 13:16
od Maranov
Ne, proto je tam ten while, čte to po 1024B dlouhých kouscích v cyklu. Ukládá se to za sebou.
V C# jsem tohle ještě nedělal, tak jsem si to taky zkusil...

Jednosměrná komunikace od klienta k serveru.
ServerClientTCP.zip
Můžeš vycházet z tohohle. Všimni si vytvoření Thread po přijetí připojení - server je tzv. konkurentní a může obsluhovat více připojení zároveň, takže když se jeden klient připojí, neblokuje spojení pro ostatní, vždy se vytvoří TcpClient a ten se obsluhuje v té metodě paralelně.
Ukázka, jak to funguje se třemi klienty (jeden postupně odesílá čísla 0-99, další 100-199, třetí 200-299):
konkurence.png
V případě GUI aplikace ještě máš problém (na který jsi narazil), že Accept*() ti zablokuje thread a čeká. Proto aplikace zatuhne a nereaguje. Proto ho musíš spustit buď zmíněnými asynchronními metodami:
http://msdn.microsoft.com/en-us/library ... lient.aspx
nebo v druhém threadu, podobně jak je řešená konkurence.
Otázka je, co na to nemožnost upravovat vlastnosti TextBox a dalších prvků z jiného threadu... okenní aplikace jsou pro začátečníka celkem zátěž...
Re: C# - TCP
Napsal: ned 14. srp 2011, 13:34
od gorilino
Děkuji mockrát za ukázku . Jeste kdyz tam je server.Start() ... a pote je podminka while (true ) ... to znamena dokud je listener v naslouchacim modu? a jak pak vypnu naslouchaci mod? zavrenim listeneru (server.Close() )?
Re: C# - TCP
Napsal: ned 14. srp 2011, 14:03
od Maranov
Start() začne naslouchat a požadavky na připojení se začnou řadit do fronty. Při každém zavolání Accept*() je pak navázáno spojení s tím požadavkem, co je zrovna na řadě, ostatní čekají.
Proto je lepší zadat samotnou komunikaci (která funguje na jiném, automaticky přiřazeném socketu a portu) zadat jinému threadu a přijmout hned další požadavek (v onom cyklu while(true)), jinak klientům může vypršet timeout a musí se pokusit o připojení znovu.
Close() přestane zařazovat požadavky a žádné nové spojení tak nevznikne. Takže ano, přestaneš tím naslouchat.
Re: C# - TCP
Napsal: ned 14. srp 2011, 14:15
od gorilino
takze tato cast kodu dokaze obsluhovat vice klientu v jednom case ? pro kazdeho vytvori spojeni a sve vlastni vlakno? Nechapu totiz jak muze byt vice vlaken a spojeni se stejnym nazvem .. je mozne treba kdyby se pripojili tri klienti abych mel tri tcpklienty a tri vlakna se stejnym nazvem?
Omlouvam se za me blbe dotazy

ale v tomhle jsem trochu nechapavy a rad bych to pochopil
Kód: Vybrat vše
while (true)
{
TcpClient connection = server.AcceptTcpClient();
Thread worker = new Thread(new ParameterizedThreadStart(ReadMessage));
worker.Start(connection);
}
Re: C# - TCP
Napsal: ned 14. srp 2011, 19:04
od Maranov
Ty vlákna mají jiné ID. Ta hodnota ve worker se vždycky přepíše informacemi o novém vlákně, vlákno samotné si však žije vlastním životem, tu referenci de facto potřebuješ jen na nějaké operace s tím vláknem (třeba zde jeho spuštění pomocí Start(...)).
Každým zavoláním (dokončením zavolání) vzniká nové spojení, které funguje na novém socketu, má vlastní čísla portů apod. Pokud se nemýlím, vzniklá spojení budou stále otevřená, i když zavřeš TcpListener.