praegune kellaaeg 23.06.2025 02:07:02
|
Hinnavaatlus
:: Foorum
:: Uudised
:: Ärifoorumid
:: HV F1 ennustusvõistlus
:: Pangalink
:: Telekavad
:: HV toote otsing
|
|
autor |
|
Ohohh
Kreisi kasutaja

liitunud: 13.09.2003
|
20.06.2008 11:27:35
[C/C++] linux socketid |
|
|
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++:
|
/* * 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)); //linger ling; //ling.l_linger = 0; //ling.l_onoff = 0; while (1) { /*listen 1 connect request*/ listen(fd_listen, 1); size = sizeof(dest); /*retrieve a connect request*/ //setsockopt(fd_listen, SOL_SOCKET, SO_LINGER, &ling, sizeof(linger)); 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; }
|
Ü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 |
|
 |
troglodyte
Kreisi kasutaja

liitunud: 09.08.2002
|
20.06.2008 16:48:57
|
|
|
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:
|
int opt = 1; getsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
man 2 setsockopt
|
|
Kommentaarid: 34 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
0 :: |
34 |
|
tagasi üles |
|
 |
Ohohh
Kreisi kasutaja

liitunud: 13.09.2003
|
20.06.2008 20:38:17
|
|
|
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:
|
int opt = 1; 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 |
|
 |
troglodyte
Kreisi kasutaja

liitunud: 09.08.2002
|
20.06.2008 20:40:28
|
|
|
Ohjah, loodetavasti panid tähele väikest typot getsockopt vs setsockopt
|
|
Kommentaarid: 34 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
0 :: |
34 |
|
tagasi üles |
|
 |
Ohohh
Kreisi kasutaja

liitunud: 13.09.2003
|
20.06.2008 23:13:07
|
|
|
Suurepärane, töötab!
|
|
Kommentaarid: 6 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
0 :: |
6 |
|
tagasi üles |
|
 |
k2iguvahetaja
HV veteran
liitunud: 07.05.2003
|
22.06.2008 11:19:30
|
|
|
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 |
|
 |
JannoT
HV kasutaja

liitunud: 23.12.2005
|
22.06.2008 12:30:26
|
|
|
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 |
|
 |
k2iguvahetaja
HV veteran
liitunud: 07.05.2003
|
22.06.2008 20:27:35
|
|
|
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 |
|
 |
Ohohh
Kreisi kasutaja

liitunud: 13.09.2003
|
23.06.2008 17:36:32
|
|
|
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 |
|
 |
tanzanite
HV kasutaja

liitunud: 13.05.2006
|
26.06.2008 17:10:35
|
|
|
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 |
|
 |
andreie
HV vaatleja

liitunud: 09.09.2006
|
28.06.2008 14:59:00
|
|
|
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 |
|
 |
|
lisa lemmikuks |
|
|
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.
|