Salut,
J'expérimente avec construction d'un serveur utilisant la POCO librarie. Je me serve de select() pour s'assurer quelles sockets sont préparés pour lire/écrire. Si un client ferme la connexion, j'espéré que receiveBytes() ou sendBytes() sur de côté de serveur me donneraient le valeur zero. En ce cas, le serveur pourrait fermer la connexion de client. C'est le cas si je teste mon serveur avec telnet par exemple. Mais, si le client envoie les requêtes en vitesse et ferme la connexion immediatement (sans attendre la réponse), le serveur s'arrête de marcher avec le message Connection reset by peer [in file "src/ErrorHandler.cpp", line 60]. Voilà le code source
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 #ifndef SERVER_HPP #define SERVER_HPP #include <Poco/Runnable.h> #include <Poco/Net/ServerSocket.h> #include <Poco/Net/StreamSocket.h> #include <Poco/Net/Socket.h> #include <Poco/Timespan.h> #include <string> #include <map> #include <set> #include <iostream> using Poco::Runnable; using Poco::Timespan; using Poco::Net::ServerSocket; using Poco::Net::StreamSocket; using Poco::Net::Socket; using std::string; using std::map; using std::set; using std::cout; using std::endl; class Server : public Runnable { public: Server() : _serverSocket(7000) { } void run() { _serverSocket.setReuseAddress(true); _serverSocket.listen(); while (true) { Socket::SocketList reads, writes, empties; reads.push_back(_serverSocket); for (set<StreamSocket>::const_iterator it = _in.begin(); it != _in.end(); ++it) reads.push_back(*it); for (set<StreamSocket>::const_iterator it = _out.begin(); it != _out.end(); ++it) writes.push_back(*it); _serverSocket.select(reads, writes, empties, Timespan()); for (Socket::SocketList::const_iterator it = reads.begin(); it != reads.end(); ++it) if (*it == _serverSocket) { StreamSocket peer = _serverSocket.acceptConnection(); _in.insert(peer); cout << "client accepted" << endl; } else { const short BUF_SIZE = 128; char buf[BUF_SIZE]; StreamSocket peer = static_cast<StreamSocket>(*it); int result = peer.receiveBytes(reinterpret_cast<void*>(buf), BUF_SIZE - 2); if (result == 0) { cout << "cannot read, peer closed" << endl; peer.close(); _in.erase(peer); _out.erase(peer); } else { string request(buf); _requests[peer] = request; _in.erase(peer); _out.insert(peer); cout << "request=" << request << endl; } } for (Socket::SocketList::const_iterator it = writes.begin(); it != writes.end(); ++it) { StreamSocket peer = static_cast<StreamSocket>(*it); string echo = _requests[peer]; int result = peer.sendBytes(reinterpret_cast<const void*>(echo.c_str()), echo.size()); if (result == 0) { cout << "cannot write, peer closed" << endl; peer.close(); _in.erase(peer); _out.erase(peer); } else { cout << "sent echo=" << echo << endl; _in.insert(peer); _out.erase(peer); } } } } private: ServerSocket _serverSocket; set<StreamSocket> _in; set<StreamSocket> _out; map<StreamSocket, string> _requests; }; #endif // SERVER_HPPJ'ai essayé cet exemple sous Linux et FreeBSD avec le même résultat. Comment d'éviter la situation comme ça?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 #include <iostream> #include <string> #include <sstream> #include <cstdlib> #include <cassert> #include <Poco/Exception.h> #include <Poco/Net/StreamSocket.h> #include <Poco/Net/SocketAddress.h> #include <Poco/Thread.h> #include <Poco/Runnable.h> #include <Poco/Mutex.h> #include <Poco/Format.h> #include <Poco/Timespan.h> using std::cout; using std::endl; using std::string; using std::stringstream; using Poco::Exception; using Poco::Net::StreamSocket; using Poco::Net::SocketAddress; using Poco::Thread; using Poco::Runnable; class Client : public Runnable { public: void run() { StreamSocket client(SocketAddress("127.0.0.1:7000")); int rand_no = rand(); stringstream str_no; str_no << rand_no; string request = "command=login&username=pera&password=lozinka&no=" + str_no.str(); int len = client.sendBytes(request.c_str(), request.length()); cout << "Client()::run(): request: " << request << ", len=" << len << ", request.length()=" << request.length() << endl; assert(len == request.length()); if (len == 0) cout << "Client()::run(): nothing sent, server closed" << endl; else client.close(); cout << "Client()::run(): finishing" << endl; } }; int main() { while (true) { try { Client c; c.run(); Thread t; t.start(c); t.join(); cout << "main(): finishing, " << endl; } catch (Exception& exc) { cout << "main(): exc=" << exc.what() << endl; break; } } return EXIT_SUCCESS; }
Partager