Avaleht
uus teema   vasta Tarkvara »  Programmeerimine »  [C/C++] linux socketid märgi kõik teemad loetuks
märgi mitteloetuks
vaata eelmist teemat :: vaata järgmist teemat
Hinnavaatlus :: Foorum :: Uudised :: Ärifoorumid :: HV F1 ennustusvõistlus :: Pangalink :: Telekavad :: HV toote otsing
autor
sõnum Saada viide sõbrale.  :: Teata moderaatorile teata moderaatorile
otsing:  
Ohohh
Kreisi kasutaja
Ohohh

liitunud: 13.09.2003




sõnum 20.06.2008 11:27:35 [C/C++] linux socketid vasta tsitaadiga

Ma ei saa kuidagi socketeid korralikult tööle...

Leidsin sellise näidiskoodi:
See ei ole enam oma algsel kujul. Näiteks väline while tsükkel on minu lisatud (võibolla on valesti, kuna ei tea täpselt mida tuleb socketi uuesti ühendamisel välja kutsuda)
c++:
  1.  
  2. /*
  3. *      Description:
  4. *            tcp server example
  5. *            tcp echo server: listen tcp port 4000, and echo back the received data.
  6. *
  7. *            What is shown in this example:
  8. *            1. How to program a tcp echo server
  9. *
  10. */
  11. #include <stdio.h>
  12. #include <errno.h>
  13. #include <sys/socket.h>
  14. #include <arpa/inet.h>
  15. #include <netinet/in.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18.  
  19. #include <iostream>
  20.  
  21. using namespace std;
  22.  
  23. int main(int argc, char *argv[])
  24. {
  25.         int     fd_listen, fd_client, ret;
  26.         socklen_t size;
  27.         struct sockaddr_in dest;
  28.         char    buf[1024];
  29.  
  30.  
  31.     /*create a socket*/
  32.     fd_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  33.     if (fd_listen < 0) {
  34.         printf("socket failed\n");
  35.         return 0;
  36.     }
  37.  
  38.  
  39.     /*use bind function to associate an address with a socket*/
  40.     bzero(&dest, sizeof(dest));
  41.     dest.sin_family = AF_INET;
  42.     dest.sin_port = htons(4000);
  43.     dest.sin_addr.s_addr = htonl(INADDR_ANY);
  44.     bind(fd_listen, (struct sockaddr*)&dest, sizeof(dest));
  45.     //linger ling;
  46.     //ling.l_linger = 0;
  47.     //ling.l_onoff = 0;
  48.  
  49.     while (1) {
  50.  
  51.  
  52.         /*listen 1 connect request*/
  53.         listen(fd_listen, 1);
  54.  
  55.         size = sizeof(dest);
  56.         /*retrieve a connect request*/
  57.         //setsockopt(fd_listen, SOL_SOCKET, SO_LINGER, &ling, sizeof(linger));
  58.  
  59.         fd_client = accept(fd_listen, (struct sockaddr*)&dest, &size);
  60.  
  61.         if (fd_client == -1) {
  62.             printf("accept failed, errno: %d\r\n", errno);
  63.             shutdown(fd_listen, SHUT_RDWR);
  64.             return 0;
  65.             }
  66.             printf("accept: %s, port %d\r\n",
  67.                 inet_ntoa(dest.sin_addr), htons(dest.sin_port));
  68.  
  69.         while(1) {
  70.             /*when data received, send them back*/
  71.             ret = recv(fd_client, buf, sizeof(buf), 0);
  72.             if (ret > 0) {
  73.                 if (buf[0] == 'q') break;
  74.                 send(fd_client, buf, ret, 0);
  75.             } else if (ret == 0) {
  76.                 printf("disconnect by remote\r\n");
  77.                 break;
  78.             } else if (ret < 0) {
  79.                 printf("read from ethernet failed, errno: %d\r\n", errno);
  80.                 break;
  81.             }
  82.         }
  83.         //close(fd_listen);
  84.         //close(fd_client);
  85.         shutdown(fd_listen, SHUT_RDWR);
  86.         shutdown(fd_client, SHUT_RDWR);
  87.  
  88.     }
  89.         return 0;
  90. }


Üldiselt antud kood töötab. Kui kirjutada käsureale "telnet 127.0.0.1 4000", siis ühendab ära ja kajab kõik sisestatud märgid tagasi.
Kui telneti sulgen siis teeb korraliku disconnecti ja võin kohe uuesti telnetiga ühenduda.

Kuid probleem tekib, kui disconnecti teeb serveri pool. Lisasin rea, et q tähe korral katkestatakse ühendus. Kuid tundub, et ühendust ei katkestata korralikult, kuna pärast sellist katkestamist on umbes minutine timeout, enne kui seda porti on uuesti võimalik kasutada (kui panin nüüd pordiks näiteks 4001, siis töötab kohe).

Ilmselt tuleb enne shutdown käsku veel midagi välja kutsuda.
Aga ühtki sellist socketi funktsiooni ei tundu sys/socket.h failis olevat ( http://opengroup.org/onlinepubs/007908775/xns/syssocket.h.html )

Lugesin netist, et option SO_LINGER, peaks sellega kuidagi seotud olema. Panin seda ühte ja teise kohta, kuid ei aidanud...
Kommentaarid: 6 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 6
tagasi üles
vaata kasutaja infot saada privaatsõnum
troglodyte
Kreisi kasutaja
troglodyte

liitunud: 09.08.2002




sõnum 20.06.2008 16:48:57 vasta tsitaadiga

Pead silmas siis seda, et peale serveri programmi sulgemist, ei ole võimalik enam samasse porti (4000) kohe uuesti bindida?
Sellest ümbersaamiseks socketile pealekeerata SO_REUSEADDR :
c:
  1. int opt = 1;
  2. getsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


man 2 setsockopt
Kommentaarid: 34 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 34
tagasi üles
vaata kasutaja infot saada privaatsõnum mine selle kasutaja kodulehele
Ohohh
Kreisi kasutaja
Ohohh

liitunud: 13.09.2003




sõnum 20.06.2008 20:38:17 vasta tsitaadiga

troglodyte kirjutas:
Pead silmas siis seda, et peale serveri programmi sulgemist, ei ole võimalik enam samasse porti (4000) kohe uuesti bindida?
Sellest ümbersaamiseks socketile pealekeerata SO_REUSEADDR :
c:
  1. int opt = 1;
  2. getsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


man 2 setsockopt

Tänud! Proovin varsti järgi.
Kommentaarid: 6 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 6
tagasi üles
vaata kasutaja infot saada privaatsõnum
troglodyte
Kreisi kasutaja
troglodyte

liitunud: 09.08.2002




sõnum 20.06.2008 20:40:28 vasta tsitaadiga

Ohjah, loodetavasti panid tähele väikest typot getsockopt vs setsockopt
Kommentaarid: 34 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 34
tagasi üles
vaata kasutaja infot saada privaatsõnum mine selle kasutaja kodulehele
Ohohh
Kreisi kasutaja
Ohohh

liitunud: 13.09.2003




sõnum 20.06.2008 23:13:07 vasta tsitaadiga

Suurepärane, töötab! thumbs_up.gif
Kommentaarid: 6 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 6
tagasi üles
vaata kasutaja infot saada privaatsõnum
k2iguvahetaja
HV veteran

liitunud: 07.05.2003



Autoriseeritud ID-kaardiga

sõnum 22.06.2008 11:19:30 vasta tsitaadiga

sourcecode kuskil pastebinis vms. ei saa? siit kopides on reanumbrid ees, mai viitsi neid ära kakkuda. uuriks ka värki.
Kommentaarid: 45 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 38
tagasi üles
vaata kasutaja infot saada privaatsõnum mine selle kasutaja kodulehele
JannoT
HV kasutaja
JannoT

liitunud: 23.12.2005




sõnum 22.06.2008 12:30:26 vasta tsitaadiga

k2iguvahetaja kirjutas:
sourcecode kuskil pastebinis vms. ei saa? siit kopides on reanumbrid ees, mai viitsi neid ära kakkuda. uuriks ka värki.

ot:
Üritasid ka üldse copyda seda koodi? Numbreid ei anna copyda. Vähemasti ff3'ga mitte. Plus on olemas ka nupp märgi mis terve teksti ära märgib aga jällegi ilma numbritetta

_________________
011010000110100101101110011011100110000101110110011000010110000101110100011011000111010101110011
Kommentaarid: 5 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 5
tagasi üles
vaata kasutaja infot saada privaatsõnum
k2iguvahetaja
HV veteran

liitunud: 07.05.2003



Autoriseeritud ID-kaardiga

sõnum 22.06.2008 20:27:35 vasta tsitaadiga

Jepjep, aga kui ma pasten tulevad ikkagi millegipärast numbrid ees? Vahet pole kas kasutan märgi nuppu või hiirega selectin.
Kommentaarid: 45 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 38
tagasi üles
vaata kasutaja infot saada privaatsõnum mine selle kasutaja kodulehele
Ohohh
Kreisi kasutaja
Ohohh

liitunud: 13.09.2003




sõnum 23.06.2008 17:36:32 vasta tsitaadiga

Seda peaks saama korralikult kopida:

/*
*   Description:
*      tcp server example
*      tcp echo server: listen tcp port 4000, and echo back the received data.
*
*      What is shown in this example:
*      1. How to program a tcp echo server
*
*/
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
   int   fd_listen, fd_client, ret;
   socklen_t size;
   struct sockaddr_in dest;
   char   buf[1024];


    /*create a socket*/
    fd_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (fd_listen < 0) {
        printf("socket failed\n");
        return 0;
    }


    /*use bind function to associate an address with a socket*/
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(4000);
    dest.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(fd_listen, (struct sockaddr*)&dest, sizeof(dest));

    int opt = 1;
    setsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    while (1) {


        /*listen 1 connect request*/
        listen(fd_listen, 1);

        size = sizeof(dest);
        /*retrieve a connect request*/
        fd_client = accept(fd_listen, (struct sockaddr*)&dest, &size);

        if (fd_client == -1) {
            printf("accept failed, errno: %d\r\n", errno);
            shutdown(fd_listen, SHUT_RDWR);
            return 0;
            }
            printf("accept: %s, port %d\r\n",
                inet_ntoa(dest.sin_addr), htons(dest.sin_port));

        while(1) {
            /*when data received, send them back*/
            ret = recv(fd_client, buf, sizeof(buf), 0);
            if (ret > 0) {
                if (buf[0] == 'q') break;
                send(fd_client, buf, ret, 0);
            } else if (ret == 0) {
                printf("disconnect by remote\r\n");
                break;
            } else if (ret < 0) {
                printf("read from ethernet failed, errno: %d\r\n", errno);
                break;
            }
        }
        //close(fd_listen);
        //close(fd_client);
        shutdown(fd_listen, SHUT_RDWR);
        shutdown(fd_client, SHUT_RDWR);

    }
   return 0;
}
Kommentaarid: 6 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 6
tagasi üles
vaata kasutaja infot saada privaatsõnum
tanzanite
HV kasutaja
tanzanite

liitunud: 13.05.2006




sõnum 26.06.2008 17:10:35 vasta tsitaadiga

k2iguvahetaja kirjutas:
Jepjep, aga kui ma pasten tulevad ikkagi millegipärast numbrid ees? Vahet pole kas kasutan märgi nuppu või hiirega selectin.
Üks võimalus sellistel puhkudel on kasutada quote/tsiteeri nuppu ... just saying.
tagasi üles
vaata kasutaja infot saada privaatsõnum
andreie
HV vaatleja
andreie

liitunud: 09.09.2006




sõnum 28.06.2008 14:59:00 vasta tsitaadiga

Saab ka lihtsamalt, tuleb soketi "fd_listen" avamine tsüklist ettepoole tõsta ja tsükli sees seda üldse mitte kinni panna.
_________________
Unix survives only because everyone else has done so badly.
Kommentaarid: 5 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 5
tagasi üles
vaata kasutaja infot saada privaatsõnum
näita postitusi alates eelmisest:   
uus teema   vasta Tarkvara »  Programmeerimine »  [C/C++] linux socketid
[vaata eelmist teemat] [vaata järgmist teemat]
 lisa lemmikuks
näita foorumit:  
 ignoreeri teemat 
sa ei või postitada uusi teemasid siia foorumisse
sa ei või vastata selle foorumi teemadele
sa ei või muuta oma postitusi selles foorumis
sa ei või kustutada oma postitusi selles foorumis
sa ei või vastata küsitlustele selles foorumis
sa ei saa lisada manuseid selles foorumis
sa võid manuseid alla laadida selles foorumis



Hinnavaatlus ei vastuta foorumis tehtud postituste eest.