2013-10-29 44 views
7

Hareket halindeyken basit bir UDP sunucusu yazdım.Golang UDP sunucusunun garip davranışı

go run udp.go'u yaptığımda, gönderdiğim tüm paketleri yazdırır. Ancak, go run udp.go > out çalıştırıldığında, istemci durduğunda stdout dosyasını out dosyasına aktarmayı durdurur.

İstemci, 10k istekleri gönderen basit bir programdır. Yani dosyada gönderilen paketlerin yaklaşık% 50'si var. İstemciyi yeniden çalıştırdığımda, istemci komut dosyasını tamamlayana kadar out dosyası yeniden büyür.

Sunucu kodu: Burada

package main 

import (
    "net" 

    "fmt" 
) 

func main() { 
    addr, _ := net.ResolveUDPAddr("udp", ":2000") 
    sock, _ := net.ListenUDP("udp", addr) 

    i := 0 
    for { 
    i++ 
    buf := make([]byte, 1024) 
    rlen, _, err := sock.ReadFromUDP(buf) 
    if err != nil { 
     fmt.Println(err) 
    } 
    fmt.Println(string(buf[0:rlen])) 
    fmt.Println(i) 
    //go handlePacket(buf, rlen) 
    } 
} 

Ve istemci kodu:

package main 

import (
    "net" 

    "fmt" 
) 

func main() { 

    num := 0 
    for i := 0; i < 100; i++ { 
    for j := 0; j < 100; j++ { 
     num++ 
     con, _ := net.Dial("udp", "127.0.0.1:2000") 
     fmt.Println(num) 
     buf := []byte("bla bla bla I am the packet") 
     _, err := con.Write(buf) 
     if err != nil { 
     fmt.Println(err) 
     } 
    } 
    } 
} 
+0

İstemcideki ve sunucudaki olası hataları görmezden geliyorsunuz. İstemcinizi çalıştırırken, hemen bir çalışma zamanı hatası attı. Bir hata kontrolü ekledikten sonra: "udp'yi arayın 127.0.0.1:2000: çok fazla açık dosya". Sorununuzla ilgili bir sorun olup olmadığını bilmiyorsanız, olası tüm hatalar için çek eklemenizi rica ediyorum. Bu, sorununuzun çözümüne yol açmıyorsa, sonuçların yanına geri dönün :) – fresskoma

+0

I hata kontrolü ekledi ve böyle bir sorun yok. Müşteri çalışıyor, başka bir sunucuyla test ettim. Bu yönlendirme soket üzerinde okuma gecikme yapar ve bazı paketler kaçırır gibi görünüyor .... –

cevap

11

, bu UDP paket kaybı gibi nedeniyle UDP doğası gibi görünüyor. UDP bağlantısız olduğundan, sunucu kullanılabilir olduğunda veya veri almaya hazır olduğunda istemci ilgilenmez. Yani sunucu meşgulse, sonraki gelen datagramı işlemek için uygun olmayacaktır. netstat -u ile kontrol edebilirsiniz (UDP paket kaybı bilgilerini içermelidir). Aynı şeyin içine girdim, sunucu (alıcı taraf) gönderilen paketlere yetişemedi.

Çağrı SetReadBuffer:

İki şey (ikinci sizin örnek ile benim için çalıştı) deneyebilirsiniz. Alma soketinin, attığınız her şeyi işlemek için yeterli arabelleğe sahip olduğundan emin olun.

sock, _ := net.ListenUDP("udp", addr) 
sock.SetReadBuffer(1048576) 

bir go rutin tüm paket işleme yapın. Sunucunun alınabilmesini istediğinizde sunucunun başka bir işi yapmamasını sağlayarak saniyedeki datagramları artırmayı deneyin. Örneğin, işleme çalışmasını bir harekete geçirin, böylece ReadFromUDP() öğesini tutmayın.

//Reintroduce your go handlePacket(buf, rlen) with a count param 
func handlePacket(buf []byte, rlen int, count int) 
     fmt.Println(string(buf[0:rlen])) 
     fmt.Println(count) 
} 

...

go handlePacket(buf, rlen, i) 

Son bir seçenek:

Son olarak, ve muhtemelen istemiyor şeyi, yavaşlatmak adına, reklam istemci bir uyku koymak oranı ve sorunu da giderir. Örneğin.

+0

Bir yan notta, ReadFromUDP, bazen bir işlem gerçekleştirmeyi ve bir kanalı kaydetmeyi kolaylaştırabilen go rutinlerinden yapılabilir. – Xorlev

1

yazma ifadeleri sonrasında stdout'u senkronize deneyin. Eğer şüpheli olarak

os.Stdout.Sync() 
+0

Bence sorun bu değil.IMO stdout, aldığı her yeni satır üzerine atılır veya uygulama normal olarak "exit" kullanılarak çıkar. Bakınız [adam sayfası] (http://linux.die.net/man/3/stdout). "Akım stdout, bir terminale işaret ettiğinde satır tamponudur. Fflush (3) veya exit (3) çağrılana veya yeni satır yazdırılana kadar kısmi çizgiler görünmez." – nemo

+2

"bir uçbirime işaret ettiğinde", işleyen durum tam olarak böyle değil ve olmadığında olanıdır. Sunucu hiç çıkmadığı için Stdout çıkışta kızarmaz. –