Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Florian Fischer
emper-echo-server
Commits
2bd583cf
Commit
2bd583cf
authored
Nov 27, 2020
by
Florian Fischer
Browse files
add initial client implementation
parent
ad3888b2
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/emper-echo-client.cpp
0 → 100644
View file @
2bd583cf
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2020 Florian Fischer
#include
<arpa/inet.h>
#include
<netinet/in.h>
#include
<sys/socket.h>
#include
<unistd.h>
#include
<cassert>
#include
<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<iostream>
#include
<random>
#include
<string>
#include
"AsyncLibrary.hpp"
#include
"Common.hpp"
#include
"Fiber.hpp"
#include
"Runtime.hpp"
#define BUF_MAX 4096
static
const
int
DECIMAL
=
10
;
static
const
unsigned
DEFAULT_CLIENTS
=
10
;
static
const
unsigned
DEFAULT_MSG_LENGTH
=
128
;
static
const
unsigned
DEFAULT_ITERATIONS
=
1000
;
static
const
int
DEFAULT_PORT
=
12345
;
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
static
const
char
DEFAULT_ADDRESS
[]
=
"127.0.0.1"
;
static
auto
random_string
(
unsigned
length
)
->
std
::
string
{
std
::
mt19937
generator
{
std
::
random_device
{}()};
std
::
uniform_int_distribution
<
int
>
distribution
{
'a'
,
'z'
};
std
::
string
rand_str
(
length
,
'\0'
);
for
(
auto
&
dis
:
rand_str
)
{
dis
=
distribution
(
generator
);
}
return
rand_str
;
}
void
client_func
(
int
sockfd
,
unsigned
iterations
,
unsigned
msg_length
)
{
assert
(
msg_length
<
BUF_MAX
);
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
char
buf
[
BUF_MAX
];
for
(
size_t
i
=
0
;
i
<
iterations
;
++
i
)
{
const
auto
s
=
random_string
(
msg_length
);
size_t
bytes_send
=
0
;
while
(
bytes_send
<
s
.
length
())
{
ssize_t
new_bytes_send
=
emper
::
io
::
send_and_wait
(
sockfd
,
s
.
c_str
()
+
bytes_send
,
s
.
length
()
-
bytes_send
,
0
);
if
(
unlikely
(
new_bytes_send
==
0
))
{
std
::
cerr
<<
"socked closed by server"
<<
std
::
endl
;
return
;
}
if
(
unlikely
(
new_bytes_send
==
-
1
))
{
perror
(
"send failed"
);
return
;
}
bytes_send
+=
new_bytes_send
;
}
int
bytes_recv
=
emper
::
io
::
recv_and_wait
(
sockfd
,
buf
,
s
.
length
(),
MSG_WAITALL
);
if
(
bytes_recv
==
0
)
{
std
::
cerr
<<
"socked closed by server"
<<
std
::
endl
;
return
;
}
if
(
bytes_recv
==
-
1
)
{
perror
(
"recv failed"
);
return
;
}
if
(
strncmp
(
s
.
c_str
(),
buf
,
s
.
length
())
!=
0
)
{
std
::
cerr
<<
"unexpected string received from server"
<<
std
::
endl
;
}
shutdown
(
sockfd
,
SHUT_RDWR
);
}
}
auto
main
(
int
argc
,
char
*
argv
[])
->
int
{
unsigned
clients
=
DEFAULT_CLIENTS
;
int
port
=
DEFAULT_PORT
;
char
*
addr
=
(
char
*
)
&
DEFAULT_ADDRESS
[
0
];
unsigned
iterations
=
DEFAULT_ITERATIONS
;
unsigned
msg_length
=
DEFAULT_MSG_LENGTH
;
if
(
argc
>
1
)
{
iterations
=
(
int
)
strtol
(
argv
[
1
],
nullptr
,
DECIMAL
);
}
if
(
argc
>
2
)
{
port
=
(
int
)
strtol
(
argv
[
2
],
nullptr
,
DECIMAL
);
}
if
(
argc
>
3
)
{
addr
=
argv
[
3
];
}
Runtime
runtime
;
for
(
unsigned
i
=
0
;
i
<
clients
;
++
i
)
{
Fiber
*
client_fiber
=
Fiber
::
from
([
&
]()
{
int
sockfd
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
sockfd
==
-
1
)
{
DIE_MSG_ERRNO
(
"client socket creation failed"
);
}
struct
sockaddr_in
server_addr
;
// assign IP, PORT
memset
(
&
server_addr
,
0
,
sizeof
(
server_addr
));
server_addr
.
sin_family
=
AF_INET
;
server_addr
.
sin_addr
.
s_addr
=
inet_addr
(
addr
);
server_addr
.
sin_port
=
htons
(
port
);
if
(
emper
::
io
::
connect_and_wait
(
sockfd
,
reinterpret_cast
<
struct
sockaddr
*>
(
&
server_addr
),
sizeof
(
server_addr
))
==
-
1
)
{
DIE_MSG_ERRNO
(
"connect failed"
);
}
client_func
(
sockfd
,
iterations
,
msg_length
);
});
runtime
.
schedule
(
*
client_fiber
);
}
runtime
.
waitUntilFinished
();
}
src/meson.build
View file @
2bd583cf
configure_file(output: 'config.h', configuration: conf_data)
configure_file(output: 'config.h', configuration: conf_data)
inc = include_directories('.')
inc = include_directories('.')
cpp_exe = executable('emper-echo-client',
'emper-echo-client.cpp',
include_directories : [inc],
dependencies: dependencies)
cpp_exe = executable('emper-echo-server',
cpp_exe = executable('emper-echo-server',
'emper-echo-server.cpp',
'emper-echo-server.cpp',
include_directories : [inc],
include_directories : [inc],
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment