MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
isockstream.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "isockstream.hpp"
13#include "globals.hpp"
14#include <iostream>
15#include <cstring>
16#include <cstdlib>
17#include <errno.h>
18#ifndef _WIN32
19#include <netdb.h>
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <unistd.h>
23#else
24#include <winsock2.h>
25#include <ws2tcpip.h>
26#ifdef _MSC_VER
27typedef int ssize_t;
28// Link with ws2_32.lib
29#pragma comment(lib, "ws2_32.lib")
30#endif
31typedef int socklen_t;
32#define close closesocket
33#endif
34
35using namespace std;
36
37namespace mfem
38{
39
41{
42 portnum = port;
43
44 if ( (portID = establish()) < 0)
45 mfem::out << "Server couldn't be established on port "
46 << portnum << endl;
47 Buf = NULL;
48}
49
50int isockstream::establish()
51{
52 // char myname[129];
53 char myname[] = "localhost";
54 int sfd;
55 struct addrinfo hints, *res, *rp;
56
57 memset(&hints, 0, sizeof(hints));
58 hints.ai_family = AF_UNSPEC;
59 hints.ai_socktype = SOCK_STREAM;
60 hints.ai_protocol = 0;
61
62 int s = getaddrinfo(myname, NULL, &hints, &res);
63 if (s != 0)
64 {
65 mfem::err << "isockstream::establish(): getaddrinfo() failed!\n"
66 << "isockstream::establish(): getaddrinfo() returned: '"
67 << myname << "'" << endl;
68 error = 1;
69 return (-1);
70 }
71
72 // loop the list of address structures returned by getaddrinfo()
73 for (rp = res; rp != NULL; rp = rp->ai_next)
74 {
75 if ((sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0)
76 {
77 mfem::err << "isockstream::establish(): socket() failed!" << endl;
78 error = 2;
79 return (-1);
80 }
81
82 int on = 1;
83 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
84 {
85 mfem::err << "isockstream::establish(): setsockopt() failed!" << endl;
86 return (-1);
87 }
88
89#if defined(__APPLE__)
90 if (bind(sfd, (const struct sockaddr *)rp->ai_addr, rp->ai_addrlen) < 0)
91#else
92 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) < 0)
93#endif
94 {
95 mfem::err << "isockstream::establish(): bind() failed!" << endl;
96 close(sfd);
97 error = 3;
98 continue;
99 }
100
101 break;
102 }
103
104 // No address succeeded
105 if (rp == NULL)
106 {
107 mfem::err << "Could not bind\n";
108 return (-1);
109 }
110
111 freeaddrinfo(res);
112 listen(sfd, 4);
113 return (sfd);
114}
115
116int isockstream::read_data(int s, char *buf, int n)
117{
118 int bcount; // counts bytes read
119 int br; // bytes read this pass
120
121 bcount= 0;
122 while (bcount < n) // loop until full buffer
123 {
124 if ((br = recv(s, buf, n - bcount, 0)) > 0)
125 {
126 bcount += br; // increment byte counter
127 buf += br; // move buffer ptr for next read
128 }
129 else if (br < 0) // signal an error to the caller
130 {
131 error = 4;
132 return (-1);
133 }
134 }
135 return (bcount);
136}
137
138void isockstream::receive(std::istringstream **in)
139{
140 int size;
141 char length[32];
142
143 if ((*in) != NULL)
144 {
145 delete (*in), *in = NULL;
146 }
147
148 if (portID == -1)
149 {
150 return;
151 }
152
153 if ((socketID = accept(portID, NULL, NULL)) < 0)
154 {
155 mfem::out << "Server failed to accept connection." << endl;
156 error = 5;
157 return;
158 }
159
160 if (recv(socketID, length, 32, 0) < 0)
161 {
162 error = 6;
163 return;
164 }
165 size = atoi(length);
166
167 if (Buf != NULL)
168 {
169 delete [] Buf;
170 }
171 Buf = new char[size+1];
172 if (size != read_data(socketID, Buf, size))
173 {
174 mfem::out << "Not all the data has been read" << endl;
175 }
176#ifdef DEBUG
177 else
178 {
179 mfem::out << "Reading " << size << " bytes is successful" << endl;
180 }
181#endif
182 Buf[size] = '\0';
183
184 close(socketID);
185 (*in) = new istringstream(Buf);
186}
187
189{
190 if (Buf != NULL)
191 {
192 delete [] Buf;
193 }
194 if (portID != -1)
195 {
196 close(portID);
197 }
198}
199
200}
void receive(std::istringstream **in)
Start waiting for data and return it in an input stream.
isockstream(int port)
int socklen_t
int ssize_t
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition globals.hpp:71
RefCoord s[3]