├── README.md ├── Makefile ├── clientsocket.h ├── serversocket.h ├── client.cpp ├── httpmessage.h ├── server.cpp ├── httpmessage.cpp ├── simplesocket.h └── simplesocket.cpp /README.md: -------------------------------------------------------------------------------- 1 | This directory contains wrapper classes meant to make life easier when 2 | writing C++ code using sockets. 3 | 4 | Basically, to put up a server, use a *serversocket*; to write a 5 | client, use a *clientsocket*. Each provide methods that let you use 6 | sockets like ordinary C++ streams, including the `>>` and `<<` 7 | operators. 8 | 9 | The included server and client examples show how to use the API. 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX = clang++ 2 | CXXFLAGS = -std=c++11 -g -I. # -Weverything 3 | 4 | SRCS = server.cpp client.cpp 5 | LIBS = httpmessage.cpp simplesocket.cpp simplesocket.h serversocket.h clientsocket.h httpmessage.h 6 | 7 | all: client server 8 | 9 | client: client.cpp $(LIBS) 10 | $(CXX) $(CXXFLAGS) client.cpp simplesocket.cpp -o client 11 | 12 | server: server.cpp $(LIBS) 13 | $(CXX) $(CXXFLAGS) server.cpp simplesocket.cpp -o server -lpthread 14 | 15 | clean: 16 | rm -f server client 17 | 18 | -------------------------------------------------------------------------------- /clientsocket.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef CLIENTSOCKET_H 4 | #define CLIENTSOCKET_H 5 | 6 | #include "simplesocket.h" 7 | 8 | class clientsocket : public simplesocket { 9 | public: 10 | clientsocket (const char * str, 11 | int port, 12 | int timeout = -1, 13 | bool debug = false) 14 | : simplesocket (str, port, timeout, debug) 15 | { 16 | initializeClient(); 17 | } 18 | 19 | private: 20 | // Clients can't serve or accept connections. 21 | void serve(); 22 | simplesocket * accept(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /serversocket.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef SERVERSOCKET_H 4 | #define SERVERSOCKET_H 5 | 6 | #include "simplesocket.h" 7 | 8 | class serversocket : public simplesocket { 9 | public: 10 | serversocket (int port, int timeout = -1, bool debug = false) 11 | : simplesocket ("127.0.0.1", port, timeout, debug) 12 | { 13 | serve(); 14 | } 15 | 16 | private: 17 | 18 | // Servers don't act as clients. 19 | void initializeClient(); 20 | 21 | // Servers can't make new outgoing connections. 22 | bool connect(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /client.cpp: -------------------------------------------------------------------------------- 1 | #include "simplesocket.h" 2 | #include "clientsocket.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int main (int argc, char * argv[]) 11 | { 12 | if (argc < 3) { 13 | cerr << "Usage: " << argv[0] << " " << endl; 14 | exit (-1); 15 | } 16 | int port; 17 | int id; 18 | stringstream (argv[1]) >> port; 19 | stringstream (argv[2]) >> id; 20 | clientsocket * s = new clientsocket("127.0.0.1", port); 21 | s->connect(); 22 | stringstream output; 23 | output << "CLIENT MESSAGE FROM " << id; 24 | cout << "client about to send: " << output.str().c_str() << endl; 25 | *s << output.str(); 26 | string result; 27 | *s >> result; 28 | cout << "Received: {" << result << "}" << endl; 29 | 30 | s->close(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /httpmessage.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef HTTPMESSAGE_H 4 | #define HTTPMESSAGE_H 5 | 6 | #include "simplesocket.h" 7 | #include 8 | 9 | using namespace std; 10 | 11 | class HttpMessage 12 | { 13 | public: 14 | enum HttpMessageType 15 | { 16 | GET = 0x0, 17 | POST = 0x1, 18 | INVALID = 0x2 19 | }; 20 | 21 | HttpMessage (HttpMessageType in_type, 22 | string in_resource, 23 | string in_httpVersion) 24 | : MessageType (in_type), 25 | Resource (in_resource), 26 | HttpVersion (in_httpVersion) 27 | { } 28 | 29 | HttpMessage parseRequest (const string& in_message); 30 | void SendHttpMessage (simplesocket& s, char* in_data, size_t length); 31 | HttpMessage ReceiveHttpMessage (simplesocket& s); 32 | 33 | HttpMessageType MessageType; 34 | string Resource; 35 | string HttpVersion; 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /server.cpp: -------------------------------------------------------------------------------- 1 | #include "simplesocket.h" 2 | #include "serversocket.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int messageNumber () { 11 | static int number = 0; 12 | static pthread_mutex_t numberLock = PTHREAD_MUTEX_INITIALIZER; 13 | int v; 14 | pthread_mutex_lock (&numberLock); 15 | v = number; 16 | number++; 17 | pthread_mutex_unlock (&numberLock); 18 | return v; 19 | } 20 | 21 | void * serve (void * cv) 22 | { 23 | // Just read exactly one string. 24 | auto * c = (simplesocket *) cv; 25 | string buffer; 26 | while (true) { 27 | *c >> buffer; 28 | if (buffer == "") { 29 | break; 30 | } 31 | int num = messageNumber(); 32 | cout << "[" << num << "] " << buffer << endl; 33 | // Now reply. 34 | stringstream str; 35 | str << "Received message " << num; 36 | *c << str.str(); 37 | } 38 | delete c; 39 | return NULL; 40 | } 41 | 42 | int main (int argc, char * argv[]) 43 | { 44 | if (argc < 2) { 45 | cerr << "Usage: " << argv[0] << " " << endl; 46 | exit (-1); 47 | } 48 | int port; 49 | stringstream (argv[1]) >> port; 50 | serversocket * s = new serversocket (port); 51 | cout << "Entering loop.\n" << endl; 52 | while (true) { 53 | // Create one thread per connection. 54 | auto c = s->accept(); 55 | pthread_t * t = new pthread_t; 56 | pthread_create (t, NULL, serve, (void *) c); 57 | } 58 | // We will never get here... 59 | s->close(); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /httpmessage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "httpmessage.h" 3 | 4 | using namespace std; 5 | 6 | HttpMessage HttpMessage::ReceiveHttpMessage (simplesocket& sock) 7 | { 8 | string message; 9 | string s; 10 | char temp; 11 | while (true){ 12 | sock.recvNBytes(&temp, 1, false); 13 | s = temp; 14 | message += s; 15 | if (temp == 0xD) 16 | { 17 | sock.recvNBytes(&temp,1, false); 18 | s = temp; 19 | message += s; 20 | if (temp == 0xA) 21 | break; 22 | } 23 | } 24 | 25 | HttpMessage ret = parseRequest (message); 26 | sock.recvNBytes(&temp, 1, false); 27 | s = temp; 28 | message += s; 29 | if (temp == 0xD) { 30 | sock.recvNBytes(&temp,1, false); 31 | s = temp; 32 | message += s; 33 | if (temp == 0xA) 34 | { 35 | return ret; 36 | } 37 | } 38 | while (true) { 39 | sock.recvNBytes(&temp, 1, false); 40 | s = temp; 41 | message += s; 42 | if (temp == 0xD) { 43 | sock.recvNBytes(&temp,1, false); 44 | s = temp; 45 | message += s; 46 | if (temp == 0xA){ 47 | sock.recvNBytes(&temp,1, false); 48 | s = temp; 49 | message += s; 50 | if (temp == 0xD){ 51 | sock.recvNBytes(&temp,1, false); 52 | s = temp; 53 | message += s; 54 | if (temp == 0xA) 55 | { 56 | if (_debug) 57 | cerr << "Full message: " << message << endl; 58 | return ret; 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | void HttpMessage::SendHttpMessage (simplesocket& sock, 67 | char * in_data, 68 | size_t length) 69 | { 70 | char CR =0xD; 71 | char LF =0xA; 72 | string ResponseHeader = "HTTP/1.1 200 OK"; 73 | ResponseHeader.push_back(CR); 74 | ResponseHeader.push_back(LF); 75 | 76 | string ContentTypeHeader = "Content-Type: text/html"; 77 | ContentTypeHeader.push_back(CR); 78 | ContentTypeHeader.push_back(LF); 79 | ContentTypeHeader.push_back(CR); 80 | ContentTypeHeader.push_back(LF); 81 | 82 | string resource(in_data, length); 83 | resource.push_back(CR); 84 | resource.push_back(LF); 85 | resource.push_back(CR); 86 | resource.push_back(LF); 87 | 88 | 89 | ResponseHeader += ContentTypeHeader; 90 | ResponseHeader += resource; 91 | 92 | // unsigned char* ptr = (unsigned char*)ResponseHeader.c_str(); 93 | sock.sendNBytes( (unsigned char*)ResponseHeader.c_str(), ResponseHeader.length()); 94 | } 95 | 96 | HttpMessage HttpMessage::parseRequest (const string& in_message) 97 | { 98 | string message = in_message; 99 | int position = message.find(" "); 100 | string type = message.substr(0, position); 101 | message = message.substr(position+1); 102 | 103 | //next space 104 | position = message.find(" "); 105 | string request = message.substr(0, position); 106 | message = message.substr(position+1); 107 | 108 | //next delimiter 109 | string endmarker; 110 | endmarker.push_back('\r'); 111 | endmarker.push_back('\n'); 112 | position = message.find(endmarker); 113 | string httpversion = message.substr(0, position); 114 | 115 | HttpMessage::HttpMessageType temphttptype; 116 | if (type != "GET") 117 | temphttptype = HttpMessage::INVALID; 118 | else 119 | temphttptype = HttpMessage::GET; 120 | 121 | HttpMessage ret (temphttptype, request, httpversion); 122 | return ret; 123 | } 124 | -------------------------------------------------------------------------------- /simplesocket.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /** 4 | * @class simplesocket 5 | * @author Emery Berger 6 | * @brief A convenient wrapper for UNIX sockets. 7 | * 8 | **/ 9 | 10 | #ifndef SIMPLESOCKET_H 11 | #define SIMPLESOCKET_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include // for memset() 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace std; 31 | 32 | class simplesocket { 33 | 34 | public: 35 | 36 | enum { TIMEOUT_ERR = -2}; 37 | 38 | public: 39 | 40 | simplesocket (const char * str, 41 | int port, 42 | int timeout = -1, 43 | bool debug = false) 44 | : _nameResolved (false), 45 | _seenEof (false), 46 | _port (port), 47 | _hostname (str), 48 | _name (_hostname + string(":") + itos(_port)), 49 | _timeout (timeout), 50 | _debug (debug), 51 | _socketfd (-1) 52 | {} 53 | 54 | virtual ~simplesocket () { 55 | close(); 56 | } 57 | 58 | /// @brief Write any value out to the socket. 59 | template 60 | simplesocket& operator<<(TYPE t) { 61 | stringstream output; 62 | output << t; 63 | auto buf_str = output.str(); 64 | auto buf = buf_str.c_str(); 65 | write (buf, strlen(buf)); 66 | return *this; 67 | } 68 | 69 | /// @brief Read in a string from the socket. 70 | simplesocket& operator>>(string& t) { 71 | char buf[MAXBUF+1]; 72 | memset (buf, 0, MAXBUF+1); 73 | read (buf, MAXBUF); 74 | t = buf; 75 | return *this; 76 | } 77 | 78 | /// @brief True iff this socket is currently open. 79 | bool isOpen() const { 80 | return (_socketfd != -1); 81 | } 82 | 83 | /// @brief True iff this socket has read an EOF. 84 | bool seenEof() const { 85 | // seenEof => ! isOpen(). 86 | assert (!_seenEof || !isOpen()); 87 | return _seenEof; 88 | } 89 | 90 | /// @brief Write len bytes from a buffer into the socket. 91 | int write (const char * buf, size_t len) { 92 | return sendNBytes ((unsigned char*) buf, len, true); 93 | } 94 | 95 | /// @brief Read at most len bytes into the buffer from the socket. 96 | int read (char * buf, int len) { 97 | return recvNBytes(buf, len, true); 98 | } 99 | 100 | void setTimeout (int timeout) { 101 | if (timeout > 0) 102 | _timeout = timeout; 103 | } 104 | 105 | /// @brief The fully-qualified name (hostname + port). 106 | const char * name() const { 107 | return _name.c_str(); 108 | } 109 | 110 | /// @brief The socket's hostname. 111 | const char * hostname() const { 112 | return _hostname.c_str(); 113 | } 114 | 115 | /// @brief The socket port. 116 | int port() const { 117 | return _port; 118 | } 119 | 120 | /// @return true iff the name successfully resolved to an IP address. 121 | bool resolved (void) const { 122 | return _nameResolved; 123 | } 124 | 125 | /// @brief Close down the connection. 126 | void close(); 127 | 128 | /// @brief Receive up to (or exactly) a number of bytes of data. 129 | ssize_t recvNBytes (void* data, int size, bool lessOk=false); 130 | 131 | /// @brief Send up to (or exactly) a number of bytes of data. 132 | ssize_t sendNBytes (unsigned char* data, int size, bool lessOk=false); 133 | 134 | /// @brief Establish a connection to a remote server. 135 | bool connect(); 136 | 137 | /// @brief Act as a server and await connections. 138 | void serve(); 139 | 140 | /// @brief Accept a connection. 141 | simplesocket * accept(); 142 | 143 | void initializeClient() { 144 | // Prevent SIGPIPE signals from aborting the program. 145 | signal (SIGPIPE, SIG_IGN); 146 | resolve (NULL); 147 | } 148 | 149 | private: 150 | 151 | void resolve (struct addrinfo * hint); 152 | int descriptorReady (int fd, int timeout); 153 | 154 | struct addrinfo * _addresses; 155 | int _socketfd; 156 | bool _nameResolved; 157 | bool _seenEof; 158 | const int _port; 159 | const string _hostname; 160 | const string _name; 161 | ostringstream _str; 162 | int _timeout; 163 | bool _debug; 164 | 165 | string itos (int v) { 166 | stringstream str; 167 | str << v; 168 | return str.str(); 169 | } 170 | 171 | enum { MAXBUF = 65536 }; // largest possible input. 172 | 173 | }; 174 | 175 | #ifndef MSG_NOSIGNAL 176 | /* Operating systems which have SO_NOSIGPIPE but not MSG_NOSIGNAL */ 177 | #if defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__APPLE__) 178 | #define MSG_NOSIGNAL SO_NOSIGPIPE 179 | #else 180 | #error Your OS doesnt support MSG_NOSIGNAL or SO_NOSIGPIPE 181 | #endif 182 | #endif 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /simplesocket.cpp: -------------------------------------------------------------------------------- 1 | #include "simplesocket.h" 2 | #include 3 | #include 4 | 5 | void simplesocket::resolve (struct addrinfo * hint) { 6 | int err; 7 | int on = 1; 8 | 9 | char portStr[255]; 10 | snprintf (portStr, sizeof(portStr), "%d", _port); 11 | 12 | if ((err = getaddrinfo (hostname(), portStr, hint, &_addresses)) != 0) { 13 | if (_debug) 14 | cerr << "Error in name resolution for " << name() 15 | << ", with error " << gai_strerror(err) << "\n"; 16 | _nameResolved = false; 17 | return; 18 | } 19 | 20 | _nameResolved = true; 21 | _socketfd = socket (AF_INET, SOCK_STREAM, 0); 22 | if (_socketfd < 0) { 23 | if (_debug) 24 | cerr << "SOCKET CREATION FAILURE... aborting.\n"; 25 | return; 26 | } 27 | 28 | setsockopt (_socketfd, 29 | SOL_SOCKET, 30 | SO_REUSEADDR, 31 | (void *) &on, 32 | sizeof (on)); 33 | } 34 | 35 | void simplesocket::close(){ 36 | if (_socketfd > 0) { 37 | ::close (_socketfd); 38 | _socketfd = -1; 39 | } 40 | } 41 | 42 | int simplesocket::descriptorReady (int fd, int timeout) { 43 | assert (timeout > 0); 44 | int ret = 0; 45 | fd_set rset; 46 | FD_ZERO(&rset); 47 | FD_SET(fd, &rset); 48 | struct timeval tv; 49 | memset(&tv, 0, sizeof(struct timeval)); 50 | tv.tv_sec = timeout; 51 | tv.tv_usec = 0; 52 | do { 53 | ret = select(fd + 1, &rset, NULL, NULL, &tv); 54 | } while (ret < 0 && errno == EINTR); 55 | return ret; 56 | } 57 | 58 | ssize_t simplesocket::recvNBytes(void* data, int size, bool lessOk){ 59 | if (size<=0) return 0; 60 | int ret, nRecv = 0; 61 | int toRecv = size; 62 | do{ 63 | if (_timeout > 0){ 64 | ret = descriptorReady (_socketfd, _timeout); 65 | if (ret < 0){ 66 | assert(errno > 0 && errno!=EINTR); 67 | close(); 68 | return -errno; 69 | } else if (ret == 0) return (ssize_t)TIMEOUT_ERR; 70 | } 71 | if (_debug) cerr << "Descriptor ready, reading .. " << endl; 72 | ret = recv(_socketfd, data, toRecv, 0); 73 | if (_debug) cerr << "Recv returned error of .. " << ret << endl; 74 | if (ret<0 && errno == EINTR) continue; 75 | else if (ret<0) { 76 | assert(errno > 0); 77 | close(); 78 | return -errno; 79 | } else if (ret == 0) { 80 | _seenEof = true; 81 | close(); 82 | /* Close your side, abort connection */ 83 | break; /* Other side send a fin, tell caller */ 84 | /* Break with whatever data we could receive */ 85 | } else { 86 | data = (void*) ((unsigned long) data + ret); 87 | toRecv -= ret; 88 | nRecv += ret; 89 | } 90 | } while(toRecv > 0 && !lessOk); 91 | return nRecv; 92 | } 93 | 94 | ssize_t simplesocket::sendNBytes (unsigned char* data, int size, bool lessOk) { 95 | int ret, nSent = 0; 96 | int toSend = size; 97 | assert (toSend>0); 98 | do { 99 | ret = ::send (_socketfd, data, toSend, MSG_NOSIGNAL); 100 | if (_debug) cerr << "sent " << ret << " bytes of " << size << endl; 101 | if ((ret < 0) && (errno == EINTR)) 102 | continue; 103 | else if (ret < 0){ 104 | if (_debug) { 105 | perror ("Simplesocket error: "); 106 | } 107 | assert (errno > 0); 108 | close(); 109 | return -errno; 110 | } else if (ret == 0) { 111 | close(); 112 | return -1; /* Send shouldn't return 0 */ 113 | } else { 114 | data += ret; 115 | toSend -= ret; 116 | nSent += ret; 117 | } 118 | } while (toSend > 0 && !lessOk); 119 | return nSent; 120 | } 121 | 122 | bool simplesocket::connect (void) { 123 | long arg; 124 | fd_set myset; 125 | struct timeval tv; 126 | int valopt; 127 | socklen_t lon; 128 | int res; 129 | 130 | if (!resolved()) return false; 131 | 132 | // Stolen from the web -mdc. 133 | // Set non-blocking 134 | if( (arg = fcntl(_socketfd, F_GETFL, NULL)) < 0) { 135 | fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno)); 136 | exit(0); 137 | } 138 | arg |= O_NONBLOCK; 139 | if( fcntl(_socketfd, F_SETFL, arg) < 0) { 140 | fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno)); 141 | exit(0); 142 | } 143 | // Trying to connect with timeout 144 | res = ::connect(_socketfd, _addresses->ai_addr, _addresses->ai_addrlen); 145 | if (res < 0) { 146 | if (errno == EINPROGRESS) { 147 | // fprintf(stderr, "EINPROGRESS in connect() - selecting\n"); 148 | do { 149 | tv.tv_sec = 5; 150 | tv.tv_usec = 0; 151 | FD_ZERO(&myset); 152 | FD_SET(_socketfd, &myset); 153 | res = select(_socketfd+1, NULL, &myset, NULL, &tv); 154 | if (res < 0 && errno != EINTR) { 155 | //fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno)); 156 | res =-1; 157 | return (res >= 0); 158 | } 159 | else if (res > 0) { 160 | // Socket selected for write 161 | lon = sizeof(int); 162 | if (getsockopt(_socketfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) { 163 | fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno)); 164 | exit (0); 165 | } 166 | // Check the value returned... 167 | if (valopt) { 168 | // fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt)); 169 | res = -1; 170 | return (res >= 0); 171 | } 172 | break; 173 | } 174 | else { 175 | // fprintf(stderr, "Timeout in select() - Cancelling!\n"); 176 | res = -1; 177 | return (res >= 0); 178 | } 179 | } while (true); 180 | } 181 | else { 182 | //fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno)); 183 | res = -1; 184 | return (res >= 0); 185 | } 186 | } 187 | // Set to blocking mode again... 188 | if( (arg = fcntl(_socketfd, F_GETFL, NULL)) < 0) { 189 | fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno)); 190 | exit(0); 191 | } 192 | arg &= (~O_NONBLOCK); 193 | if( fcntl(_socketfd, F_SETFL, arg) < 0) { 194 | fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno)); 195 | exit(0); 196 | } 197 | 198 | /* if (res < 0) { 199 | if (_debug) cerr << "NO CONNECTION, errno = " << errno << endl; 200 | }*/ 201 | return (res >= 0); 202 | } 203 | 204 | void simplesocket::serve (void) 205 | { 206 | struct addrinfo hint; 207 | memset ((void *) &hint, 0, sizeof(hint)); 208 | hint.ai_flags = AI_PASSIVE; 209 | resolve (&hint); 210 | 211 | ((struct sockaddr_in*)(_addresses->ai_addr))->sin_addr.s_addr = htonl(INADDR_ANY); 212 | int r = bind (_socketfd, 213 | _addresses->ai_addr, 214 | _addresses->ai_addrlen); 215 | if (r < 0) { 216 | perror ("Bind failure."); 217 | } 218 | if (_debug) cerr << "waiting for a connection - " << _name << endl; 219 | r = listen (_socketfd, 255); 220 | if (r < 0) { 221 | if (_debug) cerr << "LISTEN FAILURE.\n"; 222 | } 223 | } 224 | 225 | simplesocket * simplesocket::accept() { 226 | socklen_t len = sizeof(_addresses); 227 | int newfd = ::accept (_socketfd, _addresses->ai_addr, &len); 228 | if (newfd < 0) { 229 | if (_debug) cerr << "ACCEPT FAILURE.\n"; 230 | return NULL; 231 | } 232 | simplesocket * newSock = new simplesocket (_hostname.c_str(), _port, -1, _debug); 233 | newSock->_socketfd = newfd; 234 | newSock->_nameResolved = true; 235 | return newSock; 236 | } 237 | 238 | --------------------------------------------------------------------------------