Socket Bağlantı Yavaşlığı
-
merhaba arkadaşlar.
bir proje için basit şekilde socket bağlantı örneği yaptım ancak sorunum şu google chrome tarayıcısı üzerinden localhost:8080 yazdığım zaman ilk etapta boş sayfa geliyor sayfayı yenileme yaptığım zaman biraz yükleme beklentisinden sonra ekrana merhaba dünya yazıyor bu sorunu nasıl aşabilirim direk localhost:8080 yazdığım zaman hello world gelmesini hızlı cevap vermesini nasıl sağlarım.
örnek kodum.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include <time.h> char data[] = ( "HTTP/1.0 200 OK \n" "Content-Type: text/html; charset=utf-8 \n\n" "Hello World!" ); void lws_sleep(unsigned int mseconds) { sleep(mseconds); } static void lws_listen(int port, char *html_content) { struct sockaddr_in serv_addr; int listenfd = 0; int connfd = 0; char sendBuff[1025]; listenfd = socket(AF_INET, SOCK_STREAM, 0); memset(&serv_addr, '0', sizeof(serv_addr)); memset(sendBuff, '0', sizeof(sendBuff)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(port); bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); listen(listenfd, 1024); while (1) { connfd = accept(listenfd, (struct sockaddr*) NULL, NULL); strcpy(sendBuff,html_content); write(connfd,sendBuff,strlen(sendBuff)+1); close(connfd); shutdown(connfd, SHUT_RDWR); lws_sleep(1); } } int main(int argc, char *argv[]) { // lua web server socket listen lws_listen(8080,data); return 0; }
-
Linux sistemlerde soket programlama hakkında pek bilgim yok ama cevabını bende merak ediyorum sorununun. GCC de yok derleyemedim şimdilik.
-
Sorun buradaki kodlarda değil,chrome ile açtığında zaten yavaş geliyormuş, o yüzden sorunu orada aramalısın. Ayrıca çok da hızlı olmasını bekleme, localhostta çalıştırdığın ne bilmiyorum.
-
protokol seviyesinde şu olabilir
Content length headerini mutlaka ver ve doğru olsun, connection:close da ekle
soket seviyesinde SO_DONTLINGER parametresini aktif et (bu 200 ms falan etkiler en çok)
HolyOne tarafından 29/Tem/14 19:42 tarihinde düzenlenmiştir -
Bağlantıyı sonlandırmak TCP de mesele. O yüzden bak söyle yap
Hello World\r\n
0\r\n\r\n
Ordaki 0 düz 0 en sona bunu ekle. Yüzde 90 çözer
-
HolyOne bunu yazdı
Hocam tam detayını bilmiom napion ama protokol seviyesinde şu olabilir
Content length headerini mutlaka ver ve doğru olsun, connection:close da ekle
soket seviyesinde SO_DONTLINGER parametresini aktif et (bu 200 ms falan etkiler en çok)
Holy doğru testip etmiş, content-length koymadığın için header'e browser datanın bittiğini anlamıyor, devamını beklerken bağlantıyı kapatıyorsun, hiç data gelmemiş gibi hata döndürüyor.
datayı şöyle düzenle dene, bende düzeldi sorun, ayrıca o sleep i close dan sonra koymanın bir anlamı yok, zaten accept blokeli çalışır, yeni bağlantı gelene kadar bekler. önce koymanın da bir anlamı yok gerçi, write ya da send ne kadar data yolladığını döndürür, datanın tümünün tek seferde yollanacağı garanti değildir, döngü içinde hepsi gidene kadar yollaman lazım.
char *data = ("HTTP/1.0 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Content-Length: 12\r\n\r\n"
"Hello World!");
-
haklısınız arkadaşlar herkese tek tek teşekkür ederim sorun düzeldi hemen ekrana geliyor. 2 sorum daha olacak arkadaşlar.
1. ./program --port:8080 yazıyorum buradaki --port:8080 yazısını okuyabiliyorum argv üzerinden ancak gelen datayı parse edip : dan sonraki bilgi almak ve bunu int olarak cevirme işlemini nasıl yaparım.
2. thread'lar ile gelen istekler için thread oluşturup gelen isteğe cevap verdikten sonra sonlanmasını sağlamak istiyorum bunu nasıl yaparım örnek şema aşağıdaki gibi ?
+ worker thread + +
gelen istek + worker thread + ---- mutex ---- + cevap
+ worker thread + +
---------- Housekeeping ----------
-
Her bağlantıya thread açacaksan zaten kolaya kaçmış oluyorsun, thread e client soketini ver, iletişim thread içinde bağımsız olarak devam etsin, bağlantı sonlanınca thread de kapanır zaten, join etmene ya da o threadleri beklemene gerek yok.
Yani ana thread sadece listen + accept yapıyor, her bağlantı geldiğinde client socket ile thread yaratılıyor ve yeni clientler beklenmeye devam ediyor.
Event driven kullanman daha faydalı olur nonblock mode ile, select + nonblock dene istersen. Böylece 50 bağlantıda server'ın çökmez, bkz: c10k problem.
ilk soru kolay, hata kontrolü olmadan tek satırda parse edersin,
sscanf(strchr(argv[1], ':') + 1, "%d", &port);
ama tabi ki öyle birşey yapma :)
Doğru ve tam kod örneği,
#include <stdio.h> int main(int argc, char *argv[]) { char *p; int port; if (argc != 2) { // usage return 1; } p = strchr(argv[1], ':'); if (p == NULL) { fprintf(stderr, "invalid input\n"); return 1; } if (sscanf(p + 1, "%d", &port) != 1) { fprintf(stderr, "invalid input\n"); return 1; } printf("%d\n", port); return 0; }
-
Tugberk bunu yazdı
Her bağlantıya thread açacaksan zaten kolaya kaçmış oluyorsun, thread e client soketini ver, iletişim thread içinde bağımsız olarak devam etsin, bağlantı sonlanınca thread de kapanır zaten, join etmene ya da o threadleri beklemene gerek yok.
Yani ana thread sadece listen + accept yapıyor, her bağlantı geldiğinde client socket ile thread yaratılıyor ve yeni clientler beklenmeye devam ediyor.
Event driven kullanman daha faydalı olur nonblock mode ile, select + nonblock dene istersen. Böylece 50 bağlantıda server'ın çökmez, bkz: c10k problem.
ilk soru kolay, hata kontrolü olmadan tek satırda parse edersin,
sscanf(strchr(argv[1], ':') + 1, "%d", &port);
ama tabi ki öyle birşey yapma :)
Doğru ve tam kod örneği,
#include <stdio.h> int main(int argc, char *argv[]) { char *p; int port; if (argc != 2) { // usage return 1; } p = strchr(argv[1], ':'); if (p == NULL) { fprintf(stderr, "invalid input\n"); return 1; } if (sscanf(p + 1, "%d", &port) != 1) { fprintf(stderr, "invalid input\n"); return 1; } printf("%d\n", port); return 0; }
Hocam şu forumda 2 kişinin bilgisine çok imreniyorum bir sen bir FireX'e. Bir konuda görmüştüm heral RCE konusuydu ondan sonra sizin postara göz attım hayranlık duymamak elde değil.
-
Gelen yanıtlara katılıyorum, doğru tespit.
Ek olarak "Boost Asio" kütüphanesine bakmanı tavsiye ederim kendinden multithread ve socket açma falan fonksiyonları mevcut çok hoşuna gider ve hızlı.
Linux te tecrübeyle sabit, farkedilir hız kazandırıyor. -
teşekkür ederim arkadaşlar peki aramızda libuv kullanan derleyebilen varmı acaba ? ben libuv kütüphanesini derleyip kullanamadım bir türlü başarabildiğim an libuv üzerinde geliştirme yapmayı düşünüyorum.