Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
N
Netlib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Daniel Müller
Netlib
Commits
e065c448
Commit
e065c448
authored
4 years ago
by
Daniel Müller
Browse files
Options
Downloads
Patches
Plain Diff
Add read functions with timeout
- Added timeout read for TcpStream and UdpSocket
parent
00be314f
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
inc/tcpstream.hpp
+40
-0
40 additions, 0 deletions
inc/tcpstream.hpp
inc/udpsocket.hpp
+34
-2
34 additions, 2 deletions
inc/udpsocket.hpp
src/tcpstream.cpp
+76
-0
76 additions, 0 deletions
src/tcpstream.cpp
src/udpsocket.cpp
+36
-2
36 additions, 2 deletions
src/udpsocket.cpp
with
186 additions
and
4 deletions
inc/tcpstream.hpp
+
40
−
0
View file @
e065c448
...
...
@@ -167,6 +167,46 @@ public:
*/
ssize_t
readAll
(
void
*
data
,
size_t
len
);
/**
* @brief Same as TcpStream::read but with a millisecond timeout. If the
* timeout is reached without receiving data, 0 is returned.
*
* If receiving fails, an exception is thrown.
*
* @param data Pointer to at least len bytes where the data received over
* the tcp connection will be stored.
* @param len The maxiumum number of bytes that will be received over the
* tcp connection.
* @param timeoutMs The number of milliseconds before a timeout occurs.
*
* @return The number of bytes that were actually received over the
* connection. This can be less than len. If a timeout occurs 0 is
* returned.
*/
ssize_t
readTimeout
(
void
*
data
,
size_t
len
,
int
timeoutMs
);
/**
* @brief Same as TcpStream::readAll but with a millisecond timeout. If
* the timeout is reached without receiving any data, 0 is returned. If
* the timout occurs after receiving some data, the number of bytes
* received before the timeout is returned as NEGATIVE. The timeout
* starts from the begining if partial data is received.
*
* If receiving failed an exception is thrown.
*
* @param data Pointer to at least len bytes where the data received over
* the tcp connection will be stored.
* @param len The number of bytes that will be received over the tcp
* connection.
* @param timeoutMs The number of milliseconds before a timeout occurs.
*
* @return The number of bytes that were actually received over the
* connection. This can be less than len if the connection is closed.
* If a timout occurs after some data was already read, the number of
* bytes is returned as negative.
*/
ssize_t
readAllTimeout
(
void
*
data
,
size_t
len
,
int
timeoutMs
);
/**
* @brief Get the socket address of the connection target.
*
...
...
This diff is collapsed.
Click to expand it.
inc/udpsocket.hpp
+
34
−
2
View file @
e065c448
...
...
@@ -138,7 +138,7 @@ public:
* @param remote A reference to a SockAddr that is used to store the origin
* of the UDP packet.
*
* @return The numbe of bytes that were actually copied.
* @return The numbe
r
of bytes that were actually copied.
*/
ssize_t
receive
(
void
*
data
,
size_t
len
,
SockAddr
&
remote
);
...
...
@@ -150,10 +150,42 @@ public:
* will be copied.
* @param len The maximum number of bytes that can be copied into data.
*
* @return The numbe of bytes that were actually copied.
* @return The numbe
r
of bytes that were actually copied.
*/
ssize_t
receive
(
void
*
data
,
size_t
len
);
/**
* @brief Receive a UDP packet and copy a maximum number of len bytes from
* the packet payload into data. Store the senders origin socket address
* into remote. If the timeout occurs, 0 is returned.
*
* @param data Pointer to at least len bytes of data in which the payload
* will be copied.
* @param len The maximum number of bytes that can be copied into data.
* @param remote A reference to a SockAddr that is used to store the origin
* of the UDP packet.
* @param timeoutMs The number of milliseconds before a timeout occurs.
*
* @return The number of bytes that were actually copied, or 0 if a timeout
* occured.
*/
ssize_t
receiveTimeout
(
void
*
data
,
size_t
len
,
SockAddr
&
remote
,
int
timeoutMs
);
/**
* @brief Receive a UDP packet and copy a maximum number of len bytes from
* the packet payload into data. The packets origin is not stored. If the
* timeout occurs, 0 is returned.
*
* @param data Pointer to at least len bytes of data in which the payload
* will be copied.
* @param len The maximum number of bytes that can be copied into data.
* @param timeoutMs The number of milliseconds before a timeout occurs.
*
* @return The number of bytes that were actually copied, or 0 if a timeout
* occured.
*/
ssize_t
receiveTimeout
(
void
*
data
,
size_t
len
,
int
timeoutMs
);
/**
* @brief Check if the socket is closed or open. Open in this case means
* bound and ready to send / receive.
...
...
This diff is collapsed.
Click to expand it.
src/tcpstream.cpp
+
76
−
0
View file @
e065c448
...
...
@@ -5,6 +5,7 @@
#include
<unistd.h>
#include
<sys/socket.h>
#include
<netinet/in.h>
#include
<poll.h>
TcpStream
::
TcpStream
(
SockAddr
_remote
)
:
remote
{
_remote
},
sockfd
{
0
}
...
...
@@ -154,6 +155,81 @@ ssize_t TcpStream::readAll(void *data, size_t len)
return
bytesReadTotal
;
}
ssize_t
TcpStream
::
readTimeout
(
void
*
data
,
size_t
len
,
int
timeoutMs
)
{
if
(
timeoutMs
<=
0
)
return
read
(
data
,
len
);
if
(
sockfd
==
0
)
throw
std
::
runtime_error
(
"Can't read from closed socket"
);
pollfd
pfd
=
{
0
};
pfd
.
fd
=
sockfd
;
pfd
.
events
=
POLLIN
;
// block until data is available or the timeout is reached
int
res
=
poll
(
&
pfd
,
1
,
timeoutMs
);
// a timout occured
if
(
res
==
0
)
return
0
;
// a poll error occured
if
(
res
<
0
)
{
close
();
throw
std
::
runtime_error
(
"Error while reading from socket"
);
}
ssize_t
bytes_read
=
::
read
(
sockfd
,
data
,
len
);
if
(
bytes_read
<
0
)
{
close
();
throw
std
::
runtime_error
(
"Error while reading from socket"
);
}
return
bytes_read
;
}
ssize_t
TcpStream
::
readAllTimeout
(
void
*
data
,
size_t
len
,
int
timeoutMs
)
{
if
(
timeoutMs
<=
0
)
return
readAll
(
data
,
len
);
if
(
sockfd
==
0
)
throw
std
::
runtime_error
(
"Can't read from closed socket"
);
pollfd
pfd
=
{
0
};
pfd
.
fd
=
sockfd
;
pfd
.
events
=
POLLIN
;
size_t
bytesReadTotal
=
0
;
while
(
true
)
{
// block until data is available or the timeout is reached
int
res
=
poll
(
&
pfd
,
1
,
timeoutMs
);
// a timout occured
if
(
res
==
0
)
return
-
1
*
bytesReadTotal
;
// a poll error occured
if
(
res
<
0
)
{
close
();
throw
std
::
runtime_error
(
"Error while reading from socket"
);
}
ssize_t
bytesRead
=
::
read
(
sockfd
,
(
uint8_t
*
)
data
+
bytesReadTotal
,
len
-
bytesReadTotal
);
if
(
bytesRead
==
0
)
break
;
if
(
bytesRead
<
0
)
{
close
();
throw
std
::
runtime_error
(
"Error while reading from socket"
);
}
bytesReadTotal
+=
bytesRead
;
}
return
bytesReadTotal
;
}
const
SockAddr
&
TcpStream
::
getRemoteAddr
()
const
{
return
remote
;
...
...
This diff is collapsed.
Click to expand it.
src/udpsocket.cpp
+
36
−
2
View file @
e065c448
...
...
@@ -4,6 +4,7 @@
#include
<unistd.h>
#include
<sys/socket.h>
#include
<poll.h>
UdpSocket
::
UdpSocket
(
SockAddr
_local
)
...
...
@@ -93,9 +94,10 @@ ssize_t UdpSocket::sendTo(const std::string &remoteAddrPort, const void *data, s
ssize_t
UdpSocket
::
receive
(
void
*
data
,
size_t
len
,
SockAddr
&
remote
)
{
SockAddr
::
RawSockAddr
remote_raw_saddr
=
{
0
};
socklen_t
remote_raw_socklen
=
raw_socklen
;
// TODO: Lookup flags
ssize_t
bytes_read
=
::
recvfrom
(
sockfd
,
data
,
len
,
0
,
&
remote_raw_saddr
.
generic
,
&
raw_socklen
);
ssize_t
bytes_read
=
::
recvfrom
(
sockfd
,
data
,
len
,
0
,
&
remote_raw_saddr
.
generic
,
&
remote_
raw_socklen
);
if
(
bytes_read
<
0
)
{
...
...
@@ -108,20 +110,52 @@ ssize_t UdpSocket::receive(void *data, size_t len, SockAddr &remote)
}
ssize_t
UdpSocket
::
receive
(
void
*
data
,
size_t
len
)
{
SockAddr
saddr
;
return
receive
(
data
,
len
,
saddr
);
}
ssize_t
UdpSocket
::
receiveTimeout
(
void
*
data
,
size_t
len
,
SockAddr
&
remote
,
int
timeoutMs
)
{
SockAddr
::
RawSockAddr
remote_raw_saddr
=
{
0
};
socklen_t
remote_raw_socklen
=
raw_socklen
;
pollfd
pfd
=
{
0
};
pfd
.
fd
=
sockfd
;
pfd
.
events
=
POLLIN
;
// block until data is available or the timeout is reached
int
res
=
poll
(
&
pfd
,
1
,
timeoutMs
);
// a timout occured
if
(
res
==
0
)
return
0
;
// a poll error occured
if
(
res
<
0
)
{
close
();
throw
std
::
runtime_error
(
"Error while reading from socket"
);
}
// TODO: Lookup flags
ssize_t
bytes_read
=
::
recvfrom
(
sockfd
,
data
,
len
,
0
,
&
remote_raw_saddr
.
generic
,
&
raw_socklen
);
ssize_t
bytes_read
=
::
recvfrom
(
sockfd
,
data
,
len
,
0
,
&
remote_raw_saddr
.
generic
,
&
remote_
raw_socklen
);
if
(
bytes_read
<
0
)
{
throw
std
::
runtime_error
(
"Error while reading from socket"
);
}
remote
=
SockAddr
(
&
remote_raw_saddr
.
generic
,
local
.
address
.
type
);
return
bytes_read
;
}
ssize_t
UdpSocket
::
receiveTimeout
(
void
*
data
,
size_t
len
,
int
timeoutMs
)
{
SockAddr
saddr
;
return
receiveTimeout
(
data
,
len
,
saddr
,
timeoutMs
);
}
void
UdpSocket
::
close
()
{
if
(
sockfd
!=
0
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment