C#, Async Ve Çözemediğim Bir Problem
-
Merhabalar,
Sebebini çözemediğim bir hatayla karşı karşıyayım. Şöyle anlatmaya çalışayım:
Elimde 2 class var. Bunlardan birisi ana program, diğeri async bağlantılar yapan bir TCPClient içeren başka bir class. Bu classta gelen mesajın ana programa yönlendirilmesi için bir deligate var, o deligate içinde de ana programda bulunan bir methoda referans var. Ana programa verileri alabiliyorum, gelen veri bir string. Fakat, peşpeşe çok fazla veri gelirse, o string üzerinde çalışamıyorum. string.IndexOf, StartsWith vs hepsi yanlış bilgi veriyor, fakat sadece string i yazdırdığımda doğru string olduğunu görebiliyorum. Veri akışını yavaşlatırsam hiç bir sıkıntı olmadan çalışabiliyorum. Bunun nedeni ne olabilir?
Kodun gerekli kısmını kopyalıyorum:
İlk önce ana programda çalışan method, test için:
public static void serverConnection_serverMessage(string message)
{
Console.WriteLine(message); // doğru mesaj olduğunu görebiliyorum.
Console.WriteLine(message.IndexOf(" ").ToString()); // Normal bir durumda gönderirsem index i veriyor. Fakat peşpeşe 50 mesaj gönderirsem 1 saniye içinde vs. string de boşluk olmadığını idda ediyor.
}
Bu da bağlantıyı izleyen kod:
public event serverMessageEventHandler serverMessage;
public delegate void serverMessageEventHandler(string message);
public Baglanti(string address, int port)
{
this.connection.Connect(address, port);
//Baglanabildiyse
if (this.connection.Connected)
{
//Yeni mesajlari al
connection.Client.BeginReceive(this.buffer, 0, this.buffer.Length, SocketFlags.None, new AsyncCallback(this.handleServerMessage), null);
}
}
//Mesaj geldiginde
void handleServerMessage(IAsyncResult result)
{
//Uzunlugu lazim
int receivedCount;
try
{
receivedCount = connection.Client.EndReceive(result);
}
catch
{
//Hata varsa yapacak bir sey yok
return;
}
//0 kapandi demek
if (receivedCount == 0)
{
this.Disconnect();
return;
}
//Ana programa gonder
this.serverMessage(Encoding.Default.GetString(buffer, 0, receivedCount));
//Bir sonraki mesaji bekle
connection.Client.BeginReceive(this.buffer, 0, this.buffer.Length, SocketFlags.None, new AsyncCallback(this.handleServerMessage), null);
}
-
Ana programda stringin kopyasıyla çalıştıığınızda ne sonuç veriyor peki?
-
YeniHarman bunu yazdı
Ana programda stringin kopyasıyla çalıştıığınızda ne sonuç veriyor peki?
Başka bir stringe aktarıp deneyince de aynı hocam. Miktar artınca bozuluyor hemen
-
İlginç. Bununla ilgili bir şey de bulamadım.
Yanlış değer dönen yere breakpoint koyup watch kısmında incelediniz mi? Olmadı .net fw sürümünü değiştirip deneyin.
-
YeniHarman bunu yazdı
İlginç. Bununla ilgili bir şey de bulamadım.
Yanlış değer dönen yere breakpoint koyup watch kısmında incelediniz mi? Olmadı .net fw sürümünü değiştirip deneyin.
Kodu deneme imkanınız varsa bir de siz bakar mısınız hocam? Çok garip şeyler dönüyor. WriteLine(gelenString + ": test"); yazıyorum, sadece gelen stringi yazıyor, gerisini sadece bazılarına yazıyor. Belli bir düzen de yok. Bazen birinci ve dördüncü mesaja, bazen onbirinci...
-
Çok daha derin bir sorun değilse ki sanmıyorum, GetString ile metne çevirdiğin veride yine büyük ihtimalle sonda null bayt var gibi görünüyor.
this.serverMessage(Encoding.Default.GetString(buffer, 0, receivedCount));
satırını aşağıdaki ile değiştirerek deneyebilirsin. Burada yapılan iş kabaca metinden NULL karakterlerini temizlemek.
//Ana programa gonder string hamMetin = Encoding.Default.GetString(buffer, 0, receivedCount); string temizMetin = hamMetin.Replace("\0", ""); this.serverMessage(temizMetin); -
buzukatak bunu yazdı
Çok daha derin bir sorun değilse ki sanmıyorum, GetString ile metne çevirdiğin veride yine büyük ihtimalle sonda null bayt var gibi görünüyor.
this.serverMessage(Encoding.Default.GetString(buffer, 0, receivedCount));
satırını aşağıdaki ile değiştirerek deneyebilirsin. Burada yapılan iş kabaca metinden NULL karakterlerini temizlemek.
//Ana programa gonder string hamMetin = Encoding.Default.GetString(buffer, 0, receivedCount); string temizMetin = hamMetin.Replace("\0", ""); this.serverMessage(temizMetin);Denedim hocam, hala aynı sonucu alıyorum. newline ları temizledim, null ları temizledim.
-
Normal değil mi ?
Sen Async çalıştırıyorsun , O an Socketten aynı anda 2 veri geliyor ve sen 1 veriyi yazarken diğer veriyi de üstüne yazıyorsun.
Yani
ABC -> geldi
DEF -> geldi
ADBCEF oldu ; normal bir yaklaşım. Senin buna çözüm bulman gerekiyor hocam.
Bence flag mantığını kullanmalısın. Yani bir veriyi stringe doldurmadan diğer veriyi yazdırmaman gerekiyor.
Her Async hadle fonksiyonu çağırıldığında Class oluştur bir tane
class :
UUID;
Dataşeklinde bunu da array'e at. Fonksiyon handle pozisyonuna geçtiğinde uuid ata fonksiyonun başında sen bu uuid fonksiyonuyla iş yap. Senin her datan o uuidye yazılsın ordan oku. Sen tek değişkene atıp okumaya çalışıyorsun .
EDİT ; hocam birde swapping işlemlerine dikkat et. Aynı anda 2 stringin bitme ihtimali var yada kaç tane Thread var ise işlemcide o kadar sayınca değişkenin aynı bitme ihtimali var. Ben bunu Linux tarafında her porttan gelen veri C++ ile dinliyorum Ramde bir adreste tutuyorum. veriyi okurkende C++ daki adresi ilgili programlama diline aktarıp veriyi o şekilde okuyorum. Daha hızlı oluyor C++ da socket yönetimi daha basit. Proccessleri vs de kontrol ettiğin için hangi işlem ne zaman bitmiş data neymiş hangi socketid den gelmiş alayının logunu tutabiliyorsun.
MhmdAlmz tarafından 31/Ara/18 11:58 tarihinde düzenlenmiştir -
MhmdAlmz bunu yazdı
Normal değil mi ?
Sen Async çalıştırıyorsun , O an Socketten aynı anda 2 veri geliyor ve sen 1 veriyi yazarken diğer veriyi de üstüne yazıyorsun.
Yani
ABC -> geldi
DEF -> geldi
ADBCEF oldu ; normal bir yaklaşım. Senin buna çözüm bulman gerekiyor hocam.
Bence flag mantığını kullanmalısın. Yani bir veriyi stringe doldurmadan diğer veriyi yazdırmaman gerekiyor.
Her Async hadle fonksiyonu çağırıldığında Class oluştur bir tane
class :
UUID;
Dataşeklinde bunu da array'e at. Fonksiyon handle pozisyonuna geçtiğinde uuid ata fonksiyonun başında sen bu uuid fonksiyonuyla iş yap. Senin her datan o uuidye yazılsın ordan oku. Sen tek değişkene atıp okumaya çalışıyorsun .
Merhaba hocam, benim anlayamadığım şey şu. Mesela bir örnek vereyim.
Benim veriyi işleyen methodumun içine,WriteLine(GelenVeri + ": test");
yazıyorum mesela, veriyi aldığını görebiliyorum. Ama veriyle test stringini birleştiremiyor. Hızlıca sockete 1 ile 50 arası sayılar yazdırırsam mesela, şöyle oluyor genelde:
1: test
2
3
4
5
6
7: test
8
9
...
Veriyi aldıktan sonra işleyebilmesi gerek miyor mu? O WriteLine ın altına tekrardan GelenVeri yi yazdırırsam görebiliyorum ki veri değişmemiş.
-
Hocam tam olarak programın yada algoritmanın çalışma mantığını bilmiyorum.
Fakat şöyle dene önce A istemcisi (server veya client artık neyse bundan sonra A istemcisi diyeceğim) B istemcisine veri gönderiyor
Sen A dan B ye tek tek 1 den 50 ye kadar veri gönderiyorsun.
Async fonksiyonu çalışırken
1:test
2
3
4
5
6
7:test
mi yazyor ?
yani 1 i alınca test yazıyor 7 ye kadar test yazmıyor ? Doğru mu anlıyorum ?
Böyle bir şey mümkün değil yada oradaki çalıştırdığın socketin data boyutunca veri gönderiyor ki bu saçma bir şey olur. Yani söylediğin şey mantıksız.
Yada benim sana anlattığım gibi bir olay örgüsü var.
Sen string'e 1 i yazdın sonra 1:test çıktıyı üretti. O ara Socket 6 tane daha data gönderdi.
sen 6 datayı da aynı anda o değişkene yazdın oldu mu sana
2
3
4
5
6
7
daha sonra :test ekledi sonuna senin algoritman ve sonuç çıktısı
2
3
4
5
6
7:test oldu ?
Bence senin sorunun Multi Thread hocam socket ile ilgili değil. Benim sana dediğim gibi eğer her datayı bir UUID ile tutarsan LinkedList yada bir Stack mantığı ile FIFO mantığını kullanarak O Arrayde yada listede data oldukça okursun.
-
MhmdAlmz bunu yazdı
Hocam tam olarak programın yada algoritmanın çalışma mantığını bilmiyorum.
Fakat şöyle dene önce A istemcisi (server veya client artık neyse bundan sonra A istemcisi diyeceğim) B istemcisine veri gönderiyor
Sen A dan B ye tek tek 1 den 50 ye kadar veri gönderiyorsun.
Async fonksiyonu çalışırken
1:test
2
3
4
5
6
7:test
mi yazyor ?
yani 1 i alınca test yazıyor 7 ye kadar test yazmıyor ? Doğru mu anlıyorum ?
Böyle bir şey mümkün değil yada oradaki çalıştırdığın socketin data boyutunca veri gönderiyor ki bu saçma bir şey olur. Yani söylediğin şey mantıksız.
Yada benim sana anlattığım gibi bir olay örgüsü var.
Sen string'e 1 i yazdın sonra 1:test çıktıyı üretti. O ara Socket 6 tane daha data gönderdi.
sen 6 datayı da aynı anda o değişkene yazdın oldu mu sana
2
3
4
5
6
7
daha sonra :test ekledi sonuna senin algoritman ve sonuç çıktısı
2
3
4
5
6
7:test oldu ?
Bence senin sorunun Multi Thread hocam socket ile ilgili değil. Benim sana dediğim gibi eğer her datayı bir UUID ile tutarsan LinkedList yada bir Stack mantığı ile FIFO mantığını kullanarak O Arrayde yada listede data oldukça okursun.
Keşke sorunum multithread de olsaymış hocam. Kaç saattir bu koda bakıyorum, yanlış bir şey göremiyorum. Sorun bu kısımda değild de veriyi gönderdiğim yerdeymiş. Ekstradan 2 byte gönderiyormuş, o yüzden ben gelen veriyi işleyemiyormuşum. Çözüldü sonunda :D
