GSMComm SMS delivery report - sms

I've been trying to use GSMComm library in a C# app, in order to sent SMS messages using a mobile phone (connected via USB cable) as a GSM modem.
I've read all similar threads in SO, but didn't help.
Everything works well, except the delivery reports. I set RequestStatusReport to true and i enabled notifications (EnableMessageNotifications()).
The problem is that i am not able to read the received delivery report, although i know its storage (it's always "SR") and index number. I keep getting a 321 error code (invalid index) because SR storage looks empty when i try to read from it.
The MessageReceived event code and the corresponding report are as following, any help would be greatly appreciated!
private static void Comm_MessageReceived(object sender, MessageReceivedEventArgs e)
{
IMessageIndicationObject obj = e.IndicationObject;
if (obj is MemoryLocation)
{
MemoryLocation loc = (MemoryLocation)obj;
Util.AddLog(string.Format("New message received in storage \"{0}\", index {1}.", loc.Storage, loc.Index));
DecodedShortMessage msg = Comm.ReadMessage(loc.Index, loc.Storage);
if (((SmsPdu)msg.Data) is SmsStatusReportPdu)
{
SmsStatusReportPdu data = (SmsStatusReportPdu)msg.Data;
Util.AddLog("rec msg ref #: " + data.MessageReference.ToString());
}
}
else
{
Util.AddLog("Error: Unknown notification object!");
}
}
Report:
New message received in storage "SR", index 0.
[GSM_LOG] 17:08:49.528 Reading message...
[Catch in MessageReceived] ##### ERROR: Message service error 321 occurred.
[GSM_LOG] 17:08:49.501 [gsmphone] >>
[GSM_LOG] 17:08:49.501 [gsmphone] +CDSI: "SR",0
[GSM_LOG] 17:08:49.501 [gsmphone]
[GSM_LOG] 17:08:49.501 [gsmphone] Unsolicited message: New SMS-STATUS-REPORT received (indicated by memory location)
[GSM_LOG] 17:08:49.501 [gsmphone] Firing async MessageReceived event.
[GSM_LOG] 17:08:49.528 [gsmphone] Selecting "SR" as read storage...
[GSM_LOG] 17:08:49.528 [gsmphone] << AT+CPMS="SR"
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] >> AT+CPMS="SR"
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] +CPMS: 0,0,0,23,1,40
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] OK
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] Memory status: 0/0 (0% used)
[GSM_LOG] 17:08:49.528 [gsmphone] Activating PDU mode...
[GSM_LOG] 17:08:49.528 [gsmphone] << AT+CMGF=0
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] >> AT+CMGF=0
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] OK
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] Reading message from index 0...
[GSM_LOG] 17:08:49.528 [gsmphone] << AT+CMGR=0
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] >> AT+CMGR=0
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.528 [gsmphone] +CMS ERROR: 321
[GSM_LOG] 17:08:49.528 [gsmphone]
[GSM_LOG] 17:08:49.545 [gsmphone] Failed. Phone reports message service (MS) error 321.
[GSM_LOG] 17:08:49.545 [gsmphone] AT+CMGR=0
[GSM_LOG] 17:08:49.545 [gsmphone]
[GSM_LOG] 17:08:49.545 [gsmphone] +CMS ERROR: 321
[GSM_LOG] 17:08:49.545 [gsmphone]
[GSM_LOG] 17:08:49.548 [gsmphone] Ending async MessageReceivedEventHandler call

Indication object can be MemoryLocation or ShortMessage. There was no need to read from memory location again for the ShortMessage received (which is for delivery status) as you already have the object and just need to decode it. The below works for me
private void comm_MessageReceived(object sender, MessageReceivedEventArgs e)
{
try
{
IMessageIndicationObject obj = e.IndicationObject;
if (obj is MemoryLocation)
{
MemoryLocation loc = (MemoryLocation)obj;
log.InfoFormat("New message received in storage {0}, index {1}.", loc.Storage, loc.Index);
}
else if (obj is ShortMessage)
{
ShortMessage msg = (ShortMessage)obj;
SmsPdu pdu = comm.DecodeReceivedMessage(msg);
//Here can be delivery status or received message so cast to the right type by doing type checks for SmsDeliverPdu or SmsStatusReportPdu
}
else
{
log.ErrorFormat("Unknown notification message received");
log.InfoFormat("Message indication object is {0}", e.IndicationObject);
}
}
catch (Exception ex)
{
log.ErrorFormat("An error occurred while message ws received. Error: {0}", ex.Message);
log.Error(ex);
}

Related

How to call using gen_event in Erlang?

I am using a gen_event behaviour and when i am trying to issue a gen_event:call i get the following error:
> =CRASH REPORT==== 22-Dec-2019::19:17:43.030000 === crasher:
> initial call: gen_event:init_it/6
> pid: <0.215.0>
> registered_name: hev
> exception exit: {undef,[{fm,state,[<0.215.0>],[]},
> {erl_eval,do_apply,6,
> [{file,"erl_eval.erl"},{line,684}]},
> {shell,exprs,7,[{file,"shell.erl"},{line,686}]},
> {shell,eval_exprs,7,
> [{file,"shell.erl"},{line,642}]},
> {shell,eval_loop,3,
> [{file,"shell.erl"},{line,627}]}]}
> in function gen_event:terminate_server/4 (gen_event.erl, line 354)
> ancestors: [<0.212.0>]
> message_queue_len: 1
> messages: [{'EXIT',<0.212.0>,normal}]
> links: []
> dictionary: []
> trap_exit: true
> status: running
> heap_size: 610
> stack_size: 27
> reductions: 279 neighbours:
My event manager and event handler get spawned and i can successfully issue notify (i get ok back) but i can not call:
Module
-module(hev).
-export([start/0,append/2,state/1]).
-export([init/1,terminate/2,code_change/3,handle_call/2,handle_event/2]).
-record(state,{
xs=[]
}).
-behaviour(gen_event).
%callbacks
init([])->
{ok,#state{xs=[1]}}.
**API**
start()->
{ok,Pid}=gen_event:start_link({local,?MODULE}),
gen_event:add_handler(Pid,some_handler,[]),
Pid.
append(Pid,Elem)->
gen_event:notify(Pid,{append,Elem}).
state(Pid)->
gen_event:call(Pid,state).
Handlers
handle_event({append,Elem},State=#state{xs=XS})->
{ok,#state{xs=[Elem|XS]}};
handle_call(state,State})->
{ok,State,State};
handle_call(Event,State)->
{ok,nada_for_you,State}.
P.S I have not posted all the requried methods (code_change,terminate..etc) but they exist.
I have not posted all the requried methods (code_change,terminate..etc) but they exist.
1) They are optional anyway. Check the big green Notes in the docs, e.g. terminate().
2) As for your error message:
pid: <0.215.0>
registered_name: hev
exception exit: {undef,[{fm,state,[<0.215.0>],[]},
it seems to be saying that there was a process (with pid=<0.215.0>), which was registered with the name hev, that tried to execute a function named fm:state() with one argument but there was no function fm:state/1 defined anywhere, hence the undef exception. Because you posted no module named fm, the error makes no sense in relation to the code you posted.
3) Your code also specifies a module named some_handler that does not exist:
gen_event:add_handler(Pid,some_handler,[]),
4) You have a basic syntax error here:
handle_call(state,State})->
5) You are calling a couple of functions with the wrong number of arguments.
You need to be more diligent about posting code that will actually produce the error you experienced.
Here's a simple example using gen_event to create a counter:
-module(counter).
-behaviour(gen_event).
-compile(export_all).
%% Callback functions:
init(StartingCount) -> % Called by gen_event:add_handler()
State = StartingCount,
{ok, State}.
terminate(_Reason, State) ->
io:format("Terminating state was: ~w~n", [State]).
% Calls to gen_event:notify() cause this function to execute:
handle_event({increase, Change}, State) ->
NewState = State+Change,
{ok, NewState};
handle_event({decrease, Change}, State) ->
NewState = State-Change,
{ok, NewState}.
% Calls to gen_event:call() cause this function to execute:
handle_call(get_count, State) ->
Reply = io_lib:format("Reply from handle_call(): count is ~w~n", [State]),
{ok, Reply, State};
handle_call({increase_and_get_count, Change}, State) ->
NewState = State+Change,
Reply = io_lib:format("Reply from handle_call(): count is ~w~n", [NewState]),
{ok, Reply, NewState}.
%% User interface functions:
start(StartingCount) ->
ServerName = gen_event_counter,
CallbackModule = counter,
{ok, _Pid} = gen_event:start_link({local, ServerName}),
%Name of process running gen_event server is: gen_event_counter
ok = gen_event:add_handler(ServerName, CallbackModule, StartingCount).
%StartingCount is passed to init() callback
stop() ->
ok = gen_event:stop(gen_event_counter),
stopped.
send_request_with_notify(Request) ->
gen_event:notify(gen_event_counter, Request). % returns immediately, does not wait for a reply.
% Request = {increase, 1}, {decrease, 2}, etc.
% Request is passed as first arg to handle_event().
send_request_with_call(Request) ->
Reply = gen_event:call(gen_event_counter, counter, Request), % waits for a reply
% Request is passed as first arg to handle_call()
io:format("send_request_with_call() returned => ~s", [Reply]).
In the shell:
~/erlang_programs/gen_event$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(counter).
counter.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,counter}
2> counter:start(0).
ok
3> counter:send_request_with_call(get_count).
send_request_with_call() returned => Reply from handle_call(): count is 0
ok
4> counter:send_request_with_notify({increase, 2}).
ok
5> counter:send_request_with_call(get_count).
send_request_with_call() returned => Reply from handle_call(): count is 2
ok
6> counter:send_request_with_call({increase_and_get_count, 5}).
send_request_with_call() returned => Reply from handle_call(): count is 7
ok
7> counter:stop().
Terminating state was: 7
stopped
8>
After fixing all the errors in your code:
-module(hev).
-compile(export_all).
-behaviour(gen_event).
-record(state,{
xs=[]
}).
%callbacks
init(no_args)->
{ok, #state{xs=[1]} }.
handle_event({append,Elem}, #state{xs=XS} ) ->
io:format("hev:handle_event() called~n"),
{ok, #state{xs=[Elem|XS]}}.
handle_call(get_state, State)->
Reply = State,
{ok, Reply, State};
handle_call(_Other, State)->
Reply = nada_for_you,
{ok, Reply, State}.
%**API**
start()->
gen_event:start_link({local, ?MODULE}), %Sets the gen_event server name to ?MODULE
% Server Callback Args for
% Name module init()
gen_event:add_handler(?MODULE, ?MODULE, no_args).
%Tells the gen_event server named ?MODULE to look for the callback functions
%in a module also named ?MODULE
append(Elem)->
% Server Request
% Name (matches against 1st arg in handle_event() )
gen_event:notify(?MODULE, {append, Elem}).
get_state()->
% Server Calback Request
% Name module (matches against 1st arg in handle_call() )
gen_event:call(?MODULE, ?MODULE, get_state).
other_calls() ->
gen_event:call(?MODULE, ?MODULE, {set_state, [1, 2, 3]}).
stop() ->
ok = gen_event:stop(?MODULE),
stopped.
In the shell:
~/erlang_programs/gen_event$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(hev).
hev.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,hev}
2> hev:start().
ok
3> hev:get_state().
{state,[1]}
4> hev:append(45).
ok
hev:handle_event() called
5> hev:get_state().
{state,[45,1]}
6> hev:other_calls().
nada_for_you
7> hev:stop().
stopped
8>
Note that notify() causes the handle_event() function in all the modules that were added with add_handler() to execute, whereas call() targets a specific module's handle_call() function.

Spring 5's Reactive WebClient not so asyncronous?

I met strange Spring WebClient's behavior. I have two URLs, slow and fast. Bot do nothing, but slow just wait ten seconds before response. When i call them simultaneously using WebClient, i expect fast URL will be completed earlier than slow, but actually they both completed at same time. And worst of it - sometimes it works as expected. Has anybody thoughts, why it acts in that manner, and how to make it works right? Here is my example
fun main() {
val webClient = WebClient.create()
println("${LocalDateTime.now()} [${Thread.currentThread().name}] Start")
webClient.get().uri("http://callback-mock/slow-url").exchange()
.subscribe { response ->
println("${LocalDateTime.now()} [${Thread.currentThread().name}] Executed callback slow URL with result ${response.statusCode()}")
}
webClient.get().uri("http://callback-mock/fast-url").exchange()
.subscribe { response ->
println("${LocalDateTime.now()} [${Thread.currentThread().name}] Executed callback fast URL with result ${response.statusCode()}")
}
println("${LocalDateTime.now()} [${Thread.currentThread().name}] Waiting for exit")
Thread.sleep(15_000)
println("${LocalDateTime.now()} [${Thread.currentThread().name}] Exit")
}
Result (in most cases)
2019-10-02T13:04:34.536 [main] Start
2019-10-02T13:04:35.173 [main] Waiting for exit
2019-10-02T13:04:44.791 [reactor-http-nio-4] Executed callback slow URL with result 200 OK
2019-10-02T13:04:44.791 [reactor-http-nio-2] Executed callback fast URL with result 200 OK
2019-10-02T13:04:50.193 [main] Exit
Process finished with exit code 0
In rare cases it works as expected
2019-10-02T13:23:35.619 [main] Start
2019-10-02T13:23:36.300 [main] Waiting for exit
2019-10-02T13:23:36.802 [reactor-http-nio-2] Executed callback fast URL with result 200 OK
2019-10-02T13:23:45.810 [reactor-http-nio-4] Executed callback slow URL with result 200 OK
2019-10-02T13:23:51.308 [main] Exit
Process finished with exit code 0
The following very simple test shows that fast is always returned first. (Reactor Netty is used as HTTP server)
#Test
public void test() throws InterruptedException {
DisposableServer server =
HttpServer.create()
.port(0)
.route(r -> r.get("/fast", (req,res) -> res.sendString(Mono.just("test")))
.get("/slow", (req,res) -> res.sendString(Mono.just("test").delayElement(Duration.ofSeconds(10)))))
.bindNow();
WebClient webClient = WebClient.create();
System.out.println(LocalDateTime.now() + " " + Thread.currentThread().getName() + " Start");
webClient.get().uri("http://localhost:" + server.port() + "/slow").exchange()
.subscribe(response ->
System.out.println(LocalDateTime.now() + " " + Thread.currentThread().getName() +
" Executed callback slow URL with result " + response.statusCode()));
webClient.get().uri("http://localhost:" + server.port() + "/fast").exchange()
.subscribe(response ->
System.out.println(LocalDateTime.now() + " " + Thread.currentThread().getName() +
" Executed callback fast URL with result " + response.statusCode()));
System.out.println(LocalDateTime.now() + " " + Thread.currentThread().getName() + " Waiting for exit");
Thread.sleep(15_000);
System.out.println(LocalDateTime.now() + " " + Thread.currentThread().getName() + " Exit");
server.disposeNow();
}

Can't use Vertx EventBus from official code example on Vertx.io

I have 2 very simple Vertx verticles written in Ruby:
### sender.rb
require 'vertx/vertx'
require 'date'
vertx = Vertx::Vertx.vertx()
event_bus = vertx.event_bus()
vertx.set_periodic(2000) { |v|
msg = "Ruby NOW " + DateTime.now.strftime("%H:%M:%S")
puts(msg)
event_bus.publish("news.uk.sport", msg)
}
and
### listener.rb
require 'vertx/vertx'
vertx = Vertx::Vertx.vertx()
event_bus = vertx.event_bus()
consumer = event_bus.consumer("news.uk.sport")
consumer.handler() { |message|
puts "I have received a message: #{message.body()}"
}
consumer.completion_handler() { |res_err,res|
if (res_err == nil)
puts "The handler registration has reached all nodes"
else
puts "Registration failed!"
end
}
I have constructed these two verticles exactly from the code examples from vertx.io documentation.
I open 2 terminal sessions.
In 1st terminal I deploy the sender.rb verticle:
$ vertx run sender.rb
in 2nd terminal i deploy listener.rb verticle:
$ vertx run listener.rb
The sender sends and prints messages, but listener, doesn't receive anything (no print output from listener.rb)
I have tried to run vertx with flags
-ha
and
-cluster
but it didn't help. Please help.
UPDATE
Many thanks to Tsegismont
I have re-implemented both the listener.rb and the sender.rb and it worked :)
Now i just have little question purely out of curiosity:
In my sender:
simple_eventbus git:(master) ✗ vertx run sender.rb -cluster
Starting clustering...
No cluster-host specified so using address 192.168.7.179
Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 2071 ms, time limit is 2000
Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3073 ms, time limit is 2000
You're already on a Vert.x context, are you sure you want to create a new Vertx instance?
Succeeded in deploying verticle
On Sender site: We now have a clustered event bus: #<Vertx::EventBus:0x61deddf7>
The message has been sent: 13:20:13
The message has been sent: 13:20:15
The message has been sent: 13:20:17
The sender.rb is:
require 'vertx/vertx'
require 'date'
options = {
}
Vertx::Vertx.clustered_vertx(options) { |res_err,res|
if (res_err == nil)
vertx = res
event_bus = vertx.event_bus()
puts "On Sender site: We now have a clustered event bus: #{event_bus}"
vertx.set_periodic(2000) { |v|
msg = "Message from Sender: ruby message NOW " + DateTime.now.strftime("%H:%M:%S")
puts "The message has been sent: " + DateTime.now.strftime("%H:%M:%S")
event_bus.publish("news.uk.sport", msg)
}
else
puts "Failed: #{res_err}"
end
}
and my listener.rb output:
simple_eventbus git:(master) ✗ vertx run listener.rb -cluster
Starting clustering...
No cluster-host specified so using address 192.168.7.179
Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 2169 ms, time limit is 2000
Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3172 ms, time limit is 2000
You're already on a Vert.x context, are you sure you want to create a new Vertx instance?
Succeeded in deploying verticle
On listener side: We now have a clustered event bus: #<Vertx::EventBus:0x44af7bbf>
The handler registration has reached all nodes
I have received a message: Message from Sender: ruby message NOW 13:20:13
I have received a message: Message from Sender: ruby message NOW 13:20:15
I have received a message: Message from Sender: ruby message NOW 13:20:17
The listener.rb code:
require 'vertx/vertx'
options = {
}
Vertx::Vertx.clustered_vertx(options) { |res_err,res|
if (res_err == nil)
vertx = res
event_bus = vertx.event_bus()
puts "On listener side: We now have a clustered event bus: #{event_bus}"
consumer = event_bus.consumer("news.uk.sport")
consumer.handler() { |message|
puts "I have received a message: #{message.body()}"
}
consumer.completion_handler() { |res_err,res|
if (res_err == nil)
puts "The handler registration has reached all nodes"
else
puts "Registration failed!"
end
}
else
puts "Failed: #{res_err}"
end
}
In my sender.rb the eventBus object assigned is:
#<Vertx::EventBus:0x61deddf7>
In my listener.rb it is different:
#<Vertx::EventBus:0x44af7bbf>
Is it just the object instance reference?
Doesn't have to be the same object instance to be shared?
And another question is why does it tell me onDeploy this?
Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3073 ms, time limit is 2000
You're already on a Vert.x context, are you sure you want to create a new Vertx instance?
I have run the code once: vertx run listener.rb -cluster
Why does it tell me that I am already in Vertx context?
The problem is that your code creates a standalone Vert.x instance. To create a clustered Vert.x instance, follow this example:
require 'vertx/vertx'
options = {
}
Vertx::Vertx.clustered_vertx(options) { |res_err,res|
if (res_err == nil)
vertx = res
eventBus = vertx.event_bus()
puts "We now have a clustered event bus: #{eventBus}"
else
puts "Failed: #{res_err}"
end
}
from the Vert.x Event Bus clustering documentation section.

outputting a buffer stream

I am simiply trying to display a message I receive from a tcp socket which terminates with "\r\n\r\n".
C++ however terminates immediately even though the server indicates that the message has been successfully transmitted.
void handle_read( const boost::system::error_code& error, size_t bytes_transferred)
{
std::istream response_stream(&response_);
std::string incoming;
std::string res_time = make_daytime_string();
while (std::getline(response_stream, incoming) && incoming != "\r")
std::cout << incoming << std::endl;
std::cout <<"message received on "<< res_time <<std::endl;
}
In Eclipse I see the following in consol,
(exit value = -1)
When the program is terminated, If I switch to the consol of Linux I see the following error:
* Error in `/home/administrator/Documents/eclipse/Projects/Asynchronous_TCP/Debug/Asynchronous_TCP': double free or corruption (!prev): 0x0000000001040580 *
Solved
Apperantly I only needed to resolved the socket connection

how do i correctly fork() and exit a child process when i'm using ZeroMQ

I have a simple application that listens on a ZeroMQ socket. When the client connects and requests a worker node, I fork() my process, the forked child process creates a new context and a new ZeroMQ socket. The client and the worker node perform a REQ-REP formal behaviour on that socket.
My problem is how do I can gracefully handle a shutdown of my worker node.
The client sends an EXIT message to my worker node, who needs to close its socket and its context (?)
From what I can see, the child process exits however, new clients cannot now talk to my original parent process.
Psuedo Code
while (looping) {
zmq::message_t request;
try {
socket.recv(&request); // Wait
string reqStr = string(static_cast<char *>(request.data()), request.size());
if (reqStr.compare("exit") == 0) {
LOG(INFO) << "exiting.." << endl;
looping = false;
}
LOG(INFO) << "******************************************************************" << endl;
LOG(INFO) << "Received request for an endpoint " << reqStr << endl;
int port = doFork(reqStr);
if (port > 0) {
LOG(INFO) << "Returning endPoint: " << reqStr << " on port: " << port << endl;
string result = NumberToString(port);
zmq::message_t reply(result.length());
memcpy((void *) reply.data(), result.c_str(), result.length());
socket.send(reply);
}
else {
// Child Process exiting OR error in Fork"
looping = false;
child = true;
}
}
catch (zmq::error_t &e) {
LOG(INFO) << "W: Caught Exception OR Interrupt: " << e.what() << " : and pid is " << getpid() << endl;
}
}
if (!child) {
socket.close();
context.close();
LOG(INFO) << "Closed socket and context for pid " << getpid() << endl;
}}
int Forker::doFork(string reqStr) {
pid_t pid;
int port = ++startingPort;
switch (pid = fork()) {
case -1:
LOG(INFO) << "Error in fork";
return -1;
case 0:
LOG(INFO) << "Created child process with pid: " << getpid() << endl;
{
ServicePtr servicePtr(new Service(NumberToString(port)));
LOG(INFO) << "Spawning on port: " << port << endl;
servicePtr->spawn();
}
LOG(INFO) << "Child Process exiting on port: " << port << endl;
return 0;
default:
LOG(INFO) << "Parent process. My process id is " << getpid() << endl;
}
return port;
}
Your psuedocode isn't enough to get much of anywhere - notably you don't define your sockets there, so I don't even know which side is the REQ and which side is the REP (or, indeed, that you're actually using those socket types), or which side binds and which side connects.
But, my first guess is that you've got an uneven send/receive pairing, and something like the following is happening:
Client binds on REQ socket, worker connects on REP socket
Client sends a request (client expects recv next)
Worker sends response (client expects send next)
Client sends a follow up message (client expects recv next)
Worker shuts down
New worker spins up
Client sends a request (ERROR - REQ sockets are strictly send/recv ordering)
IF that's what's causing your issue, you can either make sure to respond back to reset the client socket, or you can use a DEALER socket instead of REQ.

Resources