MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
isockstream.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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
35namespace mfem
36{
37
39{
40 portnum = port;
41
42 if ( (portID = establish()) < 0)
43 mfem::out << "Server couldn't be established on port "
44 << portnum << std::endl;
45 Buf = NULL;
46}
47
48int isockstream::establish()
49{
50 // char myname[129];
51 char myname[] = "localhost";
52 int sfd = -1;
53 struct addrinfo hints, *res, *rp;
54
55 memset(&hints, 0, sizeof(hints));
56 hints.ai_family = AF_UNSPEC;
57 hints.ai_socktype = SOCK_STREAM;
58 hints.ai_protocol = 0;
59
60 int s = getaddrinfo(myname, NULL, &hints, &res);
61 if (s != 0)
62 {
63 mfem::err << "isockstream::establish(): getaddrinfo() failed!\n"
64 << "isockstream::establish(): getaddrinfo() returned: '"
65 << myname << "'" << std::endl;
66 error = 1;
67 return (-1);
68 }
69
70 // loop the list of address structures returned by getaddrinfo()
71 for (rp = res; rp != NULL; rp = rp->ai_next)
72 {
73 if ((sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0)
74 {
75 mfem::err << "isockstream::establish(): socket() failed!" << std::endl;
76 error = 2;
77 return (-1);
78 }
79
80 int on = 1;
81 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
82 {
83 mfem::err << "isockstream::establish(): setsockopt() failed!" << std::endl;
84 return (-1);
85 }
86
87#if defined(__APPLE__)
88 if (bind(sfd, (const struct sockaddr *)rp->ai_addr, rp->ai_addrlen) < 0)
89#else
90 if (bind(sfd, rp->ai_addr, static_cast<socklen_t>(rp->ai_addrlen)) < 0)
91#endif
92 {
93 mfem::err << "isockstream::establish(): bind() failed!" << std::endl;
94 close(sfd);
95 error = 3;
96 continue;
97 }
98
99 break;
100 }
101
102 // No address succeeded
103 if (rp == NULL)
104 {
105 mfem::err << "Could not bind\n";
106 return (-1);
107 }
108
109 freeaddrinfo(res);
110 listen(sfd, 4);
111 return (sfd);
112}
113
114int isockstream::read_data(int s, char *buf, int n)
115{
116 int bcount; // counts bytes read
117 int br; // bytes read this pass
118
119 bcount= 0;
120 while (bcount < n) // loop until full buffer
121 {
122 if ((br = recv(s, buf, n - bcount, 0)) > 0)
123 {
124 bcount += br; // increment byte counter
125 buf += br; // move buffer ptr for next read
126 }
127 else if (br < 0) // signal an error to the caller
128 {
129 error = 4;
130 return (-1);
131 }
132 }
133 return (bcount);
134}
135
136void isockstream::receive(std::istringstream **in)
137{
138 int size;
139 char length[32];
140
141 if ((*in) != NULL)
142 {
143 delete (*in), *in = NULL;
144 }
145
146 if (portID == -1)
147 {
148 return;
149 }
150
151 if ((socketID = accept(portID, NULL, NULL)) < 0)
152 {
153 mfem::out << "Server failed to accept connection." << std::endl;
154 error = 5;
155 return;
156 }
157
158 if (recv(socketID, length, 32, 0) < 0)
159 {
160 error = 6;
161 return;
162 }
163 size = atoi(length);
164
165 if (Buf != NULL)
166 {
167 delete [] Buf;
168 }
169 Buf = new char[size+1];
170 if (size != read_data(socketID, Buf, size))
171 {
172 mfem::out << "Not all the data has been read" << std::endl;
173 }
174#ifdef DEBUG
175 else
176 {
177 mfem::out << "Reading " << size << " bytes is successful" << std::endl;
178 }
179#endif
180 Buf[size] = '\0';
181
182 close(socketID);
183 (*in) = new std::istringstream(Buf);
184}
185
187{
188 if (Buf != NULL)
189 {
190 delete [] Buf;
191 }
192 if (portID != -1)
193 {
194 close(portID);
195 }
196}
197
198}
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