source: Sophya/trunk/AddOn/TAcq/swrapsock.cc@ 3946

Last change on this file since 3946 was 3916, checked in by ansari, 15 years ago

Ajout de setsockopt(...SO_REUSEADDR...) ds ServerSocket::Initialize() pour eviter le pb d'echec de bind lors du lancement du programme, Reza 30/11/2010

File size: 8.1 KB
RevLine 
[3542]1#ifdef OSF1
2#define _XOPEN_SOURCE 500
3#endif
4#include "swrapsock.h"
5#include "sopnamsp.h"
6
7#include <time.h>
8
9#include <arpa/inet.h>
10#include <netdb.h>
11#include <sys/errno.h>
12#include <unistd.h>
13
14#include <iostream>
[3639]15#include <stdlib.h>
16#include <string.h>
[3542]17
18/*!
19 \class SOPHYA::Socket
20 \ingroup SysTools
21 \brief Base class for server and client sockets.
22
23 The class Socket is not intended for direct use. Only the derived classes
24 ServerSocket and ClientSocket should be used.
[3757]25 The Close() method should be called explicitly.
[3542]26*/
27
28/* --Methode-- */
29Socket::Socket(int s)
30{
31 skt = s;
32 tstart = tlast = (long)time(NULL);
33 totsnd = totrcv = 0;
34 dts = dtr = 0;
35 nbbs = nbbr = 0;
36 lstnbb = 0; lstdt = 0;
37 errcnt = 0;
38}
39
40/* --Methode-- */
41Socket::Socket(Socket const & a)
42{
[3757]43 Set(a);
44}
45
46
47/* --Methode-- */
48Socket::~Socket()
49{
50 // Close();
51}
52
53/* --Methode-- */
54void Socket::Set(Socket const & a)
55{
[3542]56 skt = a.skt;
57 tstart = a.tstart; tlast = a.tlast;
58 totsnd = a.totsnd; totrcv = a.totrcv;
59 dts = a.dts; dtr = a.dtr;
60 nbbs = a.nbbs; nbbr = a.nbbr;
61 lstnbb = a.lstnbb; lstdt = a.lstdt;
62 errcnt = a.errcnt;
63}
64
65
66/* --Methode-- */
67size_t Socket::Send(const char * buff, size_t len, int flag)
68{
69 ssize_t rc;
70 rc = send(skt, buff, len, flag);
71 if (rc > 0) {
72 // tlast = (long)time(NULL);
73 totsnd += rc;
74 return(rc);
75 }
76 else return 0;
77}
78
79/* --Methode-- */
80size_t Socket::Receive(char * buff, size_t len, int flag)
81{
82 ssize_t rc;
83 // int fromlen = 0;
84 bool encore = true;
85 while (encore) {
86 rc = recv(skt, buff, len, flag);
87 // rc = recvfrom(skt, buff, len, flag, NULL, &fromlen);
88 if ((rc < 1) && (errno == EAGAIN)) usleep(20000);
89 else encore = false;
90 }
91 if (rc > 0) {
92 // tlast = (long)time(NULL);
93 totrcv += rc;
94 return(rc);
95 }
96 else return 0;
97}
98
[3763]99/* --Methode-- */
100size_t Socket::SendAll(const char * buff, size_t len)
101{
102 size_t nst = 0;
103 int ntry = 0;
104 while (nst < len) {
105 size_t ns = Send(buff+nst, len-nst);
106 ntry++;
107 if (ns < 1) break;
108 nst += ns;
109 }
110 if (nst < len) {
111 cout << " Socket::SendAll() / ERROR ! ntry=" << ntry
112 << " nst=" << nst << " len=" << len << endl;
113 throw SocketException("Socket::SendAll() Error NBytesSent < len ");
114 }
115 return nst;
116}
117
118/* --Methode-- */
119size_t Socket::ReceiveAll(char * buff, size_t len)
120{
121 size_t nrt = 0;
122 int ntry = 0;
123 while (nrt < len) {
124 size_t nr = Receive(buff+nrt, len-nrt);
125 ntry++;
126 if (nr < 1) break;
127 nrt += nr;
128 }
129 if (nrt < len) {
130 cout << " Socket::ReceiveAll / ERROR ! ntry=" << ntry
131 << " nrt=" << nrt << " len=" << len << endl;
132 throw SocketException("Socket::ReceiveAll() Error NBytesRecv < len ");
133 }
134 return nrt;
135}
136
[3542]137// extern int errno;
138
139/* --Methode-- */
140int Socket::Close()
141{
142 if (skt<0) return 0;
143 int rc=-1;
144 rc = shutdown(skt, SHUT_RDWR);
145 if(rc < 0)
146 cout << "Socket::Close() Erreur: Pb shutdown() ErrNo="
147 << errno << endl;
148
149 rc = close(skt);
150 if(rc < 0)
151 cout << "Socket::Close() Erreur: Pb close() ErrNo="
152 << errno << endl;
153 skt = -1;
154 return(0);
155}
156
157
158/*!
159 \class SOPHYA::ServerSocket
160 \ingroup SysTools
161 \brief Socket wrapper class for the server side
162*/
163
164/* --Methode-- */
165ServerSocket::ServerSocket(int port, int nconmax)
166 : Socket()
167{
[3907]168 Initialize(NULL, port, nconmax);
169}
170
171/* --Methode-- */
172ServerSocket::ServerSocket(const char* inadr, int port, int nconmax)
173 : Socket()
174{
175 Initialize(inadr, port, nconmax);
176}
177
178/* --Methode-- */
179ServerSocket::ServerSocket(string const& inadr, int port, int nconmax)
180 : Socket()
181{
182 Initialize(inadr.c_str(), port, nconmax);
183}
184
185
186/* --Methode-- */
187void ServerSocket::Initialize(const char* str_inadr, int port, int nconmax)
188{
[3542]189 int s,rc;
190 s = socket(AF_INET, SOCK_STREAM, 0);
191 if (s < 0) {
[3916]192 cout << "ServerSocket::Initialize() Pb socket ErrNo=" << errno << endl;
[3907]193 throw SocketException("ServerSocket::Initialize() Pb socket()");
[3542]194 }
[3916]195
[3542]196 skt = s;
[3916]197 int soptv=1;
198 if ( setsockopt( skt, SOL_SOCKET, SO_REUSEADDR, &soptv, sizeof(soptv) ) != 0) {
199 cout << "ServerSocket::Initialize() Pb setsockopt(...SO_REUSEADDR...) ErrNo=" << errno << endl;
200 throw SocketException("ServerSocket::Initialize() Pb setsockopt(...SO_REUSEADDR...)");
201 }
[3542]202 if (nconmax <= 1) nconmax = 1;
203 NConMax = nconmax;
204 nclitot = 0;
205
206 portid = port;
207 ipskt.sin_family = AF_INET;
208 ipskt.sin_port = htons(port);
[3907]209 if (str_inadr==NULL) { // pas d'adresse IP specifie
210 ipskt.sin_addr.s_addr = INADDR_ANY;
211 }
212 else { // adresse IP specifie sous la forme uuu.xxx.yyy.zzz.
213 ipskt.sin_addr.s_addr = inet_addr(str_inadr);
214 }
[3542]215 /* Je fais un cast explicit de sockaddr_in * (Internet) en sockaddr * */
216 rc = bind(skt, (struct sockaddr *)(&ipskt), sizeof(ipskt));
217 if (rc < 0) {
218 Close();
[3907]219 cout << "ServerSocket::Initialize() Pb bind() ErrNo=" << errno << endl;
220 throw SocketException("ServerSocket::Initialize() Pb bind()");
[3542]221 }
222}
223
224/* --Methode-- */
225Socket ServerSocket::WaitClientConnection()
226{
227 int rc,s,len;
228 struct sockaddr_in cli;
229
230 rc = listen(skt, NConMax);
231 if (rc < 0) {
232 cout << "ServerSocket::WaitClientConnection() Pb listen() ErrNo="
233 << errno << endl;
234 throw SocketException("ServerSocket::WaitClientConnection() Pb listen()");
235 }
236
237 /* Je fais un cast explicit de sockaddr_in * (Internet) en sockaddr * */
238 socklen_t sl = sizeof(cli);
239 s = accept(skt, (struct sockaddr *)(&cli), &sl);
240 if(s < 0) {
241 cout << "ServerSocket::WaitClientConnection() Pb accpet() ErrNo="
242 << errno << endl;
243 throw SocketException("ServerSocket::WaitClientConnection() Pb accept()");
244 }
245 nclitot++;
246
247 return Socket(s);
248}
249
250
[3897]251/* --Methode-- */
252int ServerSocket::Close()
253{
254 if (skt<0) return 0;
255 int rc=-1;
256 /* il ne faut apparemment pas faire shutdown sur un socket serveur (non connected - ENOTCONN )
257 rc = shutdown(skt, SHUT_RDWR);
258 if(rc < 0)
259 cout << "Socket::Close() Erreur: Pb shutdown() ErrNo="
260 << errno << endl;
261 */
262 rc = close(skt);
263 if(rc < 0)
264 cout << "ServerSocket::Close() Erreur: Pb close() ErrNo="
265 << errno << endl;
266 skt = -1;
267 return(0);
268}
269
270
[3542]271/*!
272 \class SOPHYA::ClientSocket
273 \ingroup SysTools
274 \brief Socket wrapper class for the client side
275*/
276
277/* --Methode-- */
278ClientSocket::ClientSocket(string const& srvname, int port)
279 : Socket()
280{
281 InitConnection(srvname.c_str(), port);
282}
283
284/* --Methode-- */
285ClientSocket::ClientSocket(const char* srvname, int port)
286 : Socket()
287{
288 InitConnection(srvname, port);
289}
290
291/* --Methode-- */
[3757]292ClientSocket::ClientSocket(ClientSocket const& a)
293 : Socket(a)
294{
295 portid=a.portid;
296 ipskt=a.ipskt;
297}
298
299
300/* --Methode-- */
301void ClientSocket::SetC(ClientSocket const& a)
302{
303 Set(a);
304 portid=a.portid;
305 ipskt=a.ipskt;
306 return;
307}
308
309
310/* --Methode-- */
[3542]311void ClientSocket::InitConnection(const char* name, int port)
312{
313 struct hostent *server;
314 int s,rc;
315#if defined(Linux) || defined(linux)
316 typedef unsigned long in_addr_t;
317#endif
318 in_addr_t inad;
319
320 server = NULL;
321 /* Try to find out if this is a known machine name */
322 server = gethostbyname(name);
323 if(!server) {
324 /* Try it as an internet address a.b.c.d */
325 /* inad = inet_addr(name);
326 if(inad == INADDR_NONE) {
327 cout << "ClientSocket() Host identification failed inet_addr("
328 << name << ")" << endl;
329 throw SocketException("ClientSocket() Host identification failed ");
330 }
331 */
332 server = gethostbyaddr(name, strlen(name), AF_INET);
333 }
334 if(!server) {
335 cout << "ClientSocket() Host identification failed (2) for"
336 << name << endl;
337 throw SocketException("ClientSocket() Host identification failed (2)");
338 }
339
340 ipskt.sin_family = AF_INET;
341 ipskt.sin_port = htons(port);
342 memcpy(&(ipskt.sin_addr), server->h_addr, server->h_length);
343 s = socket(AF_INET, SOCK_STREAM, 0);
344 if (s < 0) {
345 cout << "ClientSocket() Erreur: Pb socket() ErrNo=" << errno << endl;
346 throw SocketException("ClientSocket() Erreur: Pb socket()");
347 }
348
349
350 skt = s;
351 portid = port;
352/* Je fais un cast explicit de sockaddr_in * (Internet) en sockaddr * */
353 rc = connect(skt, (struct sockaddr *)(&ipskt), sizeof(struct sockaddr_in));
354 if (rc < 0) {
355 cout << "ClientSocket() Erreur: Pb connect() ErrNo=" << errno << endl;
356 Close();
357 throw SocketException("ClientSocket() Erreur: Pb connect()");
358 }
359}
Note: See TracBrowser for help on using the repository browser.