MFEM  v4.1.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
isockstream.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2020, 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 <netinet/in.h>
20 #include <netdb.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <unistd.h>
24 #else
25 #include <winsock.h>
26 typedef int ssize_t;
27 typedef int socklen_t;
28 #define close closesocket
29 // Link with ws2_32.lib
30 #pragma comment(lib, "ws2_32.lib")
31 #endif
32 
33 using namespace std;
34 
35 namespace mfem
36 {
37 
38 isockstream::isockstream(int port)
39 {
40  portnum = port;
41 
42  if ( (portID = establish()) < 0)
43  mfem::out << "Server couldn't be established on port "
44  << portnum << endl;
45  Buf = NULL;
46 }
47 
48 int isockstream::establish()
49 {
50  // char myname[129];
51  char myname[] = "localhost";
52  int port;
53  struct sockaddr_in sa;
54  struct hostent *hp;
55 
56  memset(&sa, 0, sizeof(struct sockaddr_in));
57  // gethostname(myname, 128);
58  hp= gethostbyname(myname);
59 
60  if (hp == NULL)
61  {
62  mfem::err << "isockstream::establish(): gethostbyname() failed!\n"
63  << "isockstream::establish(): gethostname() returned: '"
64  << myname << "'" << endl;
65  error = 1;
66  return (-1);
67  }
68 
69  sa.sin_family= hp->h_addrtype;
70  sa.sin_port= htons(portnum);
71 
72  if ((port = socket(AF_INET, SOCK_STREAM, 0)) < 0)
73  {
74  mfem::err << "isockstream::establish(): socket() failed!" << endl;
75  error = 2;
76  return (-1);
77  }
78 
79  int on=1;
80  setsockopt(port, SOL_SOCKET, SO_REUSEADDR, (char *)(&on), sizeof(on));
81 
82  if (bind(port,(const sockaddr*)&sa,(socklen_t)sizeof(struct sockaddr_in)) < 0)
83  {
84  mfem::err << "isockstream::establish(): bind() failed!" << endl;
85  close(port);
86  error = 3;
87  return (-1);
88  }
89 
90  listen(port, 4);
91  error = 0;
92  return (port);
93 }
94 
95 int isockstream::read_data(int s, char *buf, int n)
96 {
97  int bcount; // counts bytes read
98  int br; // bytes read this pass
99 
100  bcount= 0;
101  while (bcount < n) // loop until full buffer
102  {
103  if ((br = recv(s, buf, n - bcount, 0)) > 0)
104  {
105  bcount += br; // increment byte counter
106  buf += br; // move buffer ptr for next read
107  }
108  else if (br < 0) // signal an error to the caller
109  {
110  error = 4;
111  return (-1);
112  }
113  }
114  return (bcount);
115 }
116 
117 void isockstream::receive(std::istringstream **in)
118 {
119  int size;
120  char length[32];
121 
122  if ((*in) != NULL)
123  {
124  delete (*in), *in = NULL;
125  }
126 
127  if (portID == -1)
128  {
129  return;
130  }
131 
132  if ((socketID = accept(portID, NULL, NULL)) < 0)
133  {
134  mfem::out << "Server failed to accept connection." << endl;
135  error = 5;
136  return;
137  }
138 
139  if (recv(socketID, length, 32, 0) < 0)
140  {
141  error = 6;
142  return;
143  }
144  size = atoi(length);
145 
146  if (Buf != NULL)
147  {
148  delete [] Buf;
149  }
150  Buf = new char[size+1];
151  if (size != read_data(socketID, Buf, size))
152  {
153  mfem::out << "Not all the data has been read" << endl;
154  }
155 #ifdef DEBUG
156  else
157  {
158  mfem::out << "Reading " << size << " bytes is successful" << endl;
159  }
160 #endif
161  Buf[size] = '\0';
162 
163  close(socketID);
164  (*in) = new istringstream(Buf);
165 }
166 
167 isockstream::~isockstream()
168 {
169  if (Buf != NULL)
170  {
171  delete [] Buf;
172  }
173  if (portID != -1)
174  {
175  close(portID);
176  }
177 }
178 
179 }
int socklen_t
Definition: isockstream.cpp:27
int ssize_t
Definition: isockstream.cpp:26
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
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