Skip to content
Updated Multi Server Mode for NetGear API (markdown) authored by Abhishek Thakur's avatar Abhishek Thakur
...@@ -4,73 +4,123 @@ ...@@ -4,73 +4,123 @@
# Multi-Server Mode for NetGear API # Multi-Server Mode for NetGear API
_This mode is an exclusive designed NetGear API for robustly handling Multiple Servers at once, through Publish/Subscribe (`zmq.PUB/zmq.SUB`) and Request/Reply(`zmq.REQ/zmq.REP`) messaging patterns, thereby providing seamless access to unidirectional frames and data transfer from various Sources/Servers/Devices across the network in real-time._ **This mode can be easily activated through `multiserver_mode` boolean attribute in [**option](netgear#parameters-and-attributes-wrench) dictionary parameter of the Netgear API during its initialization.** > _In this exclusive mode, NetGear API robustly handles Multiple Servers at once through its Publish/Subscribe (`zmq.PUB/zmq.SUB`) and Request/Reply(`zmq.REQ/zmq.REP`) messaging patterns, thereby providing seamless access to frames and unidirectional data transfer from multiple Sources/Servers/Devices across the network in real-time._
### Key Points This mode can be easily activated through `multiserver_mode` boolean attribute in [`**option`](netgear#parameters-and-attributes-wrench) dictionary parameter of Netgear API, during its initialization.
* Enables Multiple Server messaging support with a single client.
* Ability to [send any additional data](#2-advanced-multi-server-mode-implementation-with-custom-message-transfer-and-filter-support) of any datatype along with frames in real-time.  
* Number of Servers can be extended to several 100s depending upon your System Hardware and requirements.
* Employs **Publish/Subscribe & Request/Reply** messaging patterns. ### Key Features
* Each new Server on the network can be identified on the single Client's end by using its **unique port address**.
* API actively tracks the current state of each connected Server. * _Enables Multiple Server messaging support with a single client._
* If all the connected servers on the network get disconnected, the client itself automatically exits to save resources.
* _Ability to [send any additional data](#2-advanced-multi-server-mode-implementation-with-custom-message-transfer-and-filter-support) of any datatype along with frames in real-time._
* _Number of Servers can be extended to several 100s depending upon your System Hardware and requirements._
* _Employs powerful **Publish/Subscribe & Request/Reply** messaging patterns._
* _Each new Server on the network can be identified on the single Client's end by using its **unique port address**._
* _API actively tracks the current state of each connected Server._
* _If all the connected servers on the network get disconnected, the client itself automatically exits to save resources._
   
--- ---
### Important :warning: ### Important Information :warning:
* **In Multi-Server Mode:** * **In Multi-Server Mode:**
* _A unique [`port`](netgear#parameters-and-attributes-wrench) address MUST be assigned to each Server on the network. **NOT a single port address must match!**_
* _A list/tuple of [`port`](netgear#parameters-and-attributes-wrench) addresses of each connected Server must be provided at Client's end._ * _A unique PORT address **MUST** be assigned to each Server on the network using its [`port`](netgear#parameters-and-attributes-wrench) parameter._
* _The network IP [`address`](netgear#parameters-and-attributes-wrench) value of each Server MUST exactly match the Client._ * _A list/tuple of PORT addresses of all connected Servers **MUST** be assigned at Client's end using its [`port`](netgear#parameters-and-attributes-wrench) parameter for a successful connection._
* _If all the connected servers on the network get disconnected, the Client itself automatically exits to save resources._ * _The [`address`](netgear#parameters-and-attributes-wrench) parameter value of each Server **MUST** exactly match the Client._
* _In Multi-Server Mode, even it is not advisable, when you're running all Multiple Servers and the Client on same local machine/system in different command-line windows, Avoid using NetGear API with other VidGear APIs (such as CamGear, PiGear) but instead stick to simple OpenCV methods(_usage given below_) to avoid undesired latency due to multiple threads._
* _In Multi-Server Mode, If all the connected servers on the network get disconnected, the Client itself automatically exits to save resources._
--- ---
   
## Parameters:  
**To manipulate this exclusive Multi-Server Mode, NetGear API currently provide following attribute of the [**option](netgear#parameters-and-attributes-wrench) dictionary parameters:** ### Table of Contents
* [**Attributes and Parameters**](#attributes-and-parameters)
* [Attributes](#attributes)
* [Parameters](#parameters)
* [**Usage**](#usage-hammer)
* [Multi-Server Mode using OpenCV with NetGear](#multi-server-mode-using-opencv-with-netgear)
* [Multi-Server Mode with Custom Message Transfer](#multi-server-mode-with-custom-message-transfer)
* [Multi-Server Mode with Custom Filter](#multi-server-mode-with-custom-filter)
 
 
## Attributes and Parameters:
### Attributes:
To tweak Multi-Server Mode, NetGear API provide certain internal attribute for its [`**option`](netgear#parameters-and-attributes-wrench)** dictionary parameter, which are discussed as follows:
* **`multiserver_mode`** (_boolean_) : This attribute activates Multi-Server Mode if it is set to `True`. Its default value is `False`. Its usage is as follows:
* `multiserver_mode` (_bool_): This attribute activates Multi-Server Mode if it is set to `True`. Its usage is as follows:
```python ```python
options = {'multiserver_mode':True} # activates Multi-Server Mode options = {'multiserver_mode':True} # activates Multi-Server Mode
``` ```
**:bulb: See its usage example [below](#1-implementation-using-opencv-with-netgear-api)**
* `filter` (_string_): A custom user-defined filter to allow only specific Server port at the Clients-End in Multi-Server Mode. Therefore only Server port for certain signature/value will be allowed to send data to the client. It can be used as follows: * **`filter`** (_string_): this attribute assigns a custom topic filter to allow only specific Servers at the Clients-end in Multi-Server Mode only. Its usage is as follows:
```python ```python
options = {'multiserver_mode':True, 'filter':'5565'} #activate Multi-Server Mode and set filter to allow data from port 5565 only options = {'multiserver_mode':True, 'filter':'5565'} # activate Multi-Server Mode and set filter to allow data from topic `5565` only
``` ```
**:bulb: See its usage example [below](#2-implementation-using-various-vidgear-apis-with-netgear-api)** ### Parameters:
> NetGear API also supports real-time unidirectional data transfer along with frames in Multi-Server Mode.
* **`message`:** **[For Server-end only]** enables us to send data(_of any datatype_) directly to `recv()` function at Client's end through its `send()` function. **See its usage example [below](#2-implementation-using-various-vidgear-apis-with-netgear-api)**
 
 
# Usage :hammer:
   
---
### Note :bulb:
* _For sake of simplicity, in these examples we will use only two unique Servers, but the number of these Servers can be extended to several numbers depending upon your requirements and System configurations._
# Usage: * _All of these Servers will be transferring frames to a single Client system at the same time, which will be displaying received frames as a montage(multiple frames concatenated together)._
_**:bulb:NOTE:** For sake of simplicity in these examples, **We will use only two unique Servers, but the number of these Servers can be extended to several numbers depending upon your requirements and System configurations.** All of these Servers can transfer frames to a sole Client at the same time, that will be displaying received outputs as a montage(multiple frames concatenated together)._ * _For building montage with simplicity at Client's end, We are going to use `imutils` python library function to build montages by concatenating various output video frames received from different servers together. Therefore, Kindly install this library with `pip install imutils`._
---
   
## 1. Multi-Server Mode implementation using OpenCV with NetGear API: ## Multi-Server Mode using OpenCV with NetGear:
In this example, we will capture live frames from two Sources _(a.k.a Servers)_ - each with a webcam using OpenCV. Then, those frames will be transferred over the network to a single system(a.k.a Client) at the same time using Multi-Server Mode, and those received frames will be displayed as a real-time montage.
_In this example, we will capture live frames from Multiple Systems(a.k.a Servers) with a webcam using **OpenCV computer vision library** and then transferred over the network to another system(a.k.a Client) at the same time through NetGear API using its Multi-Server Mode through **Request/Reply** Messaging pattern with insignificant latency.._
### A. Client's End Code: ### A. Client's End Code:
Open a terminal on the System(_a Client, where you want to display the input frames received from Multiple Servers_) and execute the following python code. **Remember the IP-address of this system(_required at Server's end_) by executing the command: _'`hostname -I`'_** and also replace it in the following code:
Open a terminal on the System _(a Client, where you want to display the frames received from the Multiple Servers)_ and execute the following python code:
**Note::bulb:** *For building montages with simplicity, We are going to use `imutils` python library function to build montages by concatenating various output video frames received from different servers together. Therefore, Kindly install this library with `pip3 install imutils`.* :bulb: _Remember to note the IP-address of this system(required at Server's end) by executing the command: `hostname -I` in your terminal and also replace it in the following code._
```python ```python
# import libraries # import required libraries
# import libraries
from vidgear.gears import NetGear from vidgear.gears import NetGear
from imutils import build_montages from imutils import build_montages
import cv2 import cv2
...@@ -78,16 +128,18 @@ import cv2 ...@@ -78,16 +128,18 @@ import cv2
# activate multiserver_mode # activate multiserver_mode
options = {'multiserver_mode': True} options = {'multiserver_mode': True}
#Change the Client with your system IP address and port address of each unique Server((5566,5567) in our case), plus activate pattern Request/Reply(`1`), `recieve_mode`, and `logging` for debugging # Define Netgear Client with `port` addresses of all unique Server((5566,5567) in our case). Also, Remember to change following IP address '192.168.x.xxx' with yours, plus activate Request/Reply(`1`) pattern, `recieve_mode`:
client = NetGear(address = 192.168.x.x, port = (5566,5567), protocol = 'tcp', pattern = 1, receive_mode = True, **options) client = NetGear(address = '192.168.x.x', port = (5566,5567), protocol = 'tcp', pattern = 1, receive_mode = True, **options)
#define frame received dict # Define received frame dictionary
frame_dict = {} frame_dict = {}
# infinite loop until [Ctrl+C] is pressed # loop over until Keyboard Interrupted
while True: while True:
try: try:
# receive data
# receive data from network
data = client.recv() data = client.recv()
# check if data received isn't None # check if data received isn't None
...@@ -98,13 +150,13 @@ while True: ...@@ -98,13 +150,13 @@ while True:
unique_address, frame = data unique_address, frame = data
# do something with extracted frame here # {do something with the extracted frame here}
# get extracted frame's shape # get extracted frame's shape
(h, w) = frame.shape[:2] (h, w) = frame.shape[:2]
# update the extracted frame in the frame dictionary # update the extracted frame in the received frame dictionary
frame_dict[unique_address] = frame frame_dict[unique_address] = frame
# build a montage using data dictionary # build a montage using data dictionary
...@@ -115,159 +167,168 @@ while True: ...@@ -115,159 +167,168 @@ while True:
cv2.imshow("Montage Footage {}".format(i), montage) cv2.imshow("Montage Footage {}".format(i), montage)
# detect any keypress # check for 'q' key if pressed
cv2.waitKey(1) & 0xFF key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
except KeyboardInterrupt: except KeyboardInterrupt:
break break
# finally safely close client and release resources # close output window
cv2.destroyAllWindows() cv2.destroyAllWindows()
client.close()
# safely close client
client.close()
``` ```
   
### B1. Server-1's End Code: ### B1. Server-1's End Code:
Open the terminal on System-1 (Server-1) with a webcam connected to it and execute the following python code. **Also, remember to assign and write down a unique port address(_required by Client to identify this system_) and replace the IP address with Client's IP address copied earlier** Open the terminal on System _(a.k.a Server-1)_ with a webcam connected to it and execute the following python code.
:warning: _Remember to replace the IP address in the following code with Client's IP address copied earlier and also copy the unique port address of this system(required by Client to identify this system)._
```python ```python
# import libraries # import libraries
from vidgear.gears import NetGear from vidgear.gears import NetGear
import cv2 import cv2
#Open live video stream from device at index 0 # Open suitable video stream (webcam on first index in our case)
stream = cv2.VideoCapture(0) stream = cv2.VideoCapture(0)
# activate multiserver_mode # activate multiserver_mode
options = {'multiserver_mode': True} options = {'multiserver_mode': True}
#change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address(for e.g 5566). # change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address (5566 in our case) but keep rest of settings similar to Client
server = NetGear(address = 192.168.x.x, port = '5566', protocol = 'tcp', pattern = 1, receive_mode = False, **options) # and keep rest of settings similar to Client server = NetGear(address = '192.168.x.x', port = '5566', protocol = 'tcp', pattern = 1, **options)
# infinite loop until [Ctrl+C] is pressed # loop over until Keyboard Interrupted
while True: while True:
try: try:
# read frames from stream
(grabbed, frame) = stream.read() (grabbed, frame) = stream.read()
# read frames
# check if frame is not grabbed # check for frame if not grabbed
if not grabbed: if not grabbed:
#if True break the infinite loop
break break
# do something with frame here # {do something with the frame here}
# send frame through server # send frame to server
server.send(frame) server.send(frame)
except KeyboardInterrupt: except KeyboardInterrupt:
#break the infinite loop
break break
# safely close video stream. # safely close video stream
stream.release() stream.release()
# safely close server-1
# safely close server
server.close() server.close()
``` ```
   
### B2. Server-2's End Code: ### B2. Server-2's End Code:
Similarily, Open the terminal on System-2 (Server-2) also with a webcam connected to it and execute the following python code. **Also, remember to assign and write down a unique port address(_different from System-1_) and replace the IP address with Client's IP address copied earlier** Open the terminal on System _(a.k.a Server-2)_ also with a webcam connected to it and execute the following python code.
:warning: _Remember to replace the IP address in the following code with Client's IP address copied earlier and also copy the unique port address of this system(required by Client to identify this system)._
```python ```python
# import libraries # import libraries
from vidgear.gears import NetGear from vidgear.gears import NetGear
import cv2 import cv2
#Open live video stream from device at index 1 # Open suitable video stream (webcam on first index in our case)
stream = cv2.VideoCapture(1) stream = cv2.VideoCapture(0)
# activate multiserver_mode # activate multiserver_mode
options = {'multiserver_mode': True} options = {'multiserver_mode': True}
#change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address(for e.g 5566). # change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address (5567 in our case) but keep rest of settings similar to Client
server = NetGear(address = 192.168.x.x, port = '5567', protocol = 'tcp', pattern = 1, receive_mode = False, **options) # and keep rest of settings similar to Client server = NetGear(address = '192.168.x.x', port = '5567', protocol = 'tcp', pattern = 1, **options)
# infinite loop until [Ctrl+C] is pressed # loop over until Keyboard Interrupted
while True: while True:
try: try:
# read frames from stream
(grabbed, frame) = stream.read() (grabbed, frame) = stream.read()
# read frames
# check if frame is not grabbed # check for frame if not grabbed
if not grabbed: if not grabbed:
#if True break the infinite loop
break break
# do something with frame here # {do something with the frame here}
# send frame through server # send frame to server
server.send(frame) server.send(frame)
except KeyboardInterrupt: except KeyboardInterrupt:
#break the infinite loop
break break
# safely close video stream. # safely close video stream
stream.release() stream.release()
# safely close server-1
# safely close server
server.close() server.close()
``` ```
 
   
## Multi-Server Mode with Custom Message Transfer:
## 2. Advanced Multi-Server Mode implementation with Custom Message Transfer and Filter Support: :bulb: _Remember you can send any type of additional data of any datatype along with the frame as message, for example, `dict, list, tuple,string, int etc.`!_
**Tip:bulb:: Remember you can send any type of additional data of any datatype along with the frame, for example, `dict, list, tuple,string, int etc` !** In this example, We will transfer live frames and data _(text message in this example)_ unidirectionally from different Servers _(consisting of a Raspberry Pi with RaspiCamera Module and a PC with webcam)_ to a single system _(a.k.a Client)_ over the network, where it is displayed as a real-time montage.
#### In this example we will perform the following tasks:
* _**We will capture live frames and additional data(text message in this example) using [`message` parameter in `send()` function](https://github.com/abhiTronix/vidgear/blob/8f7153cbd822da9a669cd292dc46ae4cdb8e457d/vidgear/gears/netgear.py#L423) of NetGear API**, from different Servers(consisting of a Raspberry Pi with RaspiCamera Module and a PC with webcam) and then pipe them over the network to another remote system(a.k.a Client) at the realtime._
* _**We are going to implement a [`filter`](#parameters)** at Client's end to filter out input data from only one of the give Servers_
### A. Client's End Code: ### A. Client's End Code:
Open a terminal on the remote System(_a Client, where you want to display the input frames and additional data received from Multiple Servers_) and execute the following python code. **Remember the IP-address of this system(_required at Server's end_) by executing the command _'`hostname -I`'_** and also replace it in the following code:
Open a terminal on the System _(a Client, where you want to display the frames received from the Multiple Servers)_ and execute the following python code:
**Note::bulb:** *For building montages with simplicity, We are going to use `imutils` python library function to build montages by concatenating various output video frames received from different servers together. Therefore, Kindly install this library with `pip3 install imutils`.* :bulb: _Remember to note the IP-address of this system(required at Server's end) by executing the command: `hostname -I` in your terminal and also replace it in the following code._
```python ```python
# import libraries # import required libraries
from vidgear.gears import NetGear from vidgear.gears import NetGear
from imutils import build_montages from imutils import build_montages
import cv2 import cv2
#activate multiserver_mode and filter 5567 # activate multiserver_mode
options = {'multiserver_mode': True, 'filter': 5567, 'flag' : 0, 'copy' : False, 'track' : False} options = {'multiserver_mode': True}
#Change the Client with your system IP address and port address of each unique Server((5566,5567) in our case), plus activate pattern Pub/Sub(`2`), `recieve_mode`, and `logging` for debugging # Define Netgear Client with `port` addresses of all unique Server((5577,5578) in our case). Also, Remember to change following IP address '192.168.x.xxx' with yours, plus activate Publisher/Subscriber(`2`) pattern, `recieve_mode`, and `logging` for debugging:
client = NetGear(address = 192.168.x.x, port = (5566,5567), protocol = 'tcp', pattern = 2, receive_mode = True, **options) client = NetGear(address = '192.168.x.x', port = (5577,5578), protocol = 'tcp', pattern = 2, receive_mode = True, logging = True, **options)
#define frame received dict # Define received frame dictionary
frame_dict = {} frame_dict = {}
# infinite loop until [Ctrl+C] is pressed # loop over until Keyboard Interrupted
while True: while True:
try: try:
# receive data
# receive data from network
data = client.recv() data = client.recv()
# check if data received isn't None2 # check if data received isn't None
if data is None: if data is None:
break break
# extract unique port address and its respective frame and received data # extract unique port address and its respective frame and received data
unique_address, received_data, frame = data unique_address, extracted_data, frame = data
# do something with extracted frame and data here # {do something with the extracted frame and data here}
# let's display extracted data on our extracted frame
cv2.putText(frame, received_data, (10, frame.shape[0] - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0),2) cv2.putText(frame, extracted_data, (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0),2)
# get extracted frame's shape # get extracted frame's shape
...@@ -284,64 +345,73 @@ while True: ...@@ -284,64 +345,73 @@ while True:
cv2.imshow("Montage Footage {}".format(i), montage) cv2.imshow("Montage Footage {}".format(i), montage)
# detect any keypress # check for 'q' key if pressed
cv2.waitKey(1) & 0xFF key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
except KeyboardInterrupt: except KeyboardInterrupt:
break break
# finally safely close client and release resources # close output window
cv2.destroyAllWindows() cv2.destroyAllWindows()
# safely close client
client.close() client.close()
``` ```
   
### B1. Server-1's End Code: ### B1. Server-1's End Code:
Open the terminal on System-1 (Server-1) with a webcam connected to it and execute the following python code. **Also, remember to assign and write down a unique port address(_required by Client to identify this system_) and replace the IP address with Client's IP address copied earlier** Open the terminal on System _(a.k.a Server-1)_ with a webcam connected to it and execute the following python code.
:warning: _Remember to replace the IP address in the following code with Client's IP address copied earlier and also copy the unique port address of this system(required by Client to identify this system)._
```python ```python
# import libraries # import libraries
from vidgear.gears import NetGear from vidgear.gears import NetGear
from vidgear.gears import CamGear from vidgear.gears import VideoGear
import cv2 import cv2
#Open live video stream from device at index 0 # Open suitable video stream (webcam on first index in our case)
stream = cv2.VideoCapture(0) stream = VideoGear(source=0).start()
# activate multiserver_mode # activate multiserver_mode
options = {'multiserver_mode': True, 'flag' : 0, 'copy' : False, 'track' : False} options = {'multiserver_mode': True}
#change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address(for e.g 5566). # change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address (5577 in our case) but keep rest of settings similar to Client
server = NetGear(address = 192.168.x.x, port = '5566', protocol = 'tcp', pattern = 2, receive_mode = False, **options) # and keep rest of settings similar to Client server = NetGear(address = '192.168.x.x', port = '5577', protocol = 'tcp', pattern = 2, logging = True, **options)
# infinite loop until [Ctrl+C] is pressed # loop over until Keyboard Interrupted
while True: while True:
try: try:
(grabbed, frame) = stream.read() # read frames from stream
# read frames frame = stream.read()
# check if frame is not grabbed # check for frame if Nonetype
if not grabbed: if frame is None:
#if True break the infinite loop
break break
# do something with frame and data(to be sent) here # {do something with frame and data(to be sent) here}
text = "Hello, I'm Server-1 at Port Address: 5566." # let's prepare a text string as data
text = "I'm Server-1 at Port: 5577"
# send frame and data through server # send frame and data through server
server.send(frame, message = text) server.send(frame, message = text)
except KeyboardInterrupt: except KeyboardInterrupt:
#break the infinite loop
break break
# safely close video stream. # safely close video stream
stream.release() stream.stop()
# safely close server-1
# safely close server
server.close() server.close()
``` ```
   
### B2. Server-2's End Code: ### B2. Server-2's End Code:
...@@ -354,41 +424,218 @@ from vidgear.gears import NetGear ...@@ -354,41 +424,218 @@ from vidgear.gears import NetGear
from vidgear.gears import PiGear from vidgear.gears import PiGear
import cv2 import cv2
#Open live video stream on Raspberry Pi Camera Module # add various Picamera tweak parameters to dictionary
stream = PiGear(resolution=(640, 480), framerate=60).start() options = {"hflip": True, "exposure_mode": "auto", "iso": 800, "exposure_compensation": 15, "awb_mode": "horizon", "sensor_mode": 0}
# open pi video stream with defined parameters
stream = PiGear(resolution=(640, 480), framerate=60, logging=True, **options).start()
# activate multiserver_mode # activate multiserver_mode
options = {'multiserver_mode': True, 'flag' : 0, 'copy' : False, 'track' : False} options = {'multiserver_mode': True}
#change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address(for e.g 5567) which is different from server-1. # change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address (5578 in our case) but keep rest of settings similar to Client
server = NetGear(address = '192.168.1.xxx', port = '5567', protocol = 'tcp', pattern = 2, receive_mode = False, logging = True, **options) # and keep rest of settings similar to Client server = NetGear(address = '192.168.1.xxx', port = '5578', protocol = 'tcp', pattern = 2, logging = True, **options)
# infinite loop until [Ctrl+C] is pressed # loop over until Keyboard Interrupted
while True: while True:
try: try:
# read frames from stream
frame = stream.read() frame = stream.read()
# read frames
# check if frame is not grabbed # check for frame if Nonetype
if frame is None: if frame is None:
#if True break the infinite loop
break break
# do something with frame and data(to be sent) here # {do something with frame and data(to be sent) here}
text = "Hello, I'm Server-2 at Port Address: 5567." # let's prepare a text string as data
text = "I'm Server-2 at Port: 5578"
# send frame and data through server # send frame and data through server
server.send(frame, message = text) server.send(frame, message = text)
except KeyboardInterrupt: except KeyboardInterrupt:
#break the infinite loop
break break
# safely close video stream. # safely close video stream.
stream.stop() stream.stop()
# safely close server-2
# safely close server
server.close()
```
 
 
## Multi-Server Mode with Custom Filter:
In this example, We will transfer live frames from different Servers _(each with webcam)_ to a single system _(a.k.a Client)_ over the network but we are going to implement a filter at Client's end to filter data from only one of the given Servers.
### A. Client's End Code:
Open a terminal on the System _(a Client, where you want to display the frames received from the Multiple Servers)_ and execute the following python code:
:bulb: _Remember to note the IP-address of this system(required at Server's end) by executing the command: `hostname -I` in your terminal and also replace it in the following code._
```python
# import required libraries
from vidgear.gears import NetGear
from imutils import build_montages
import cv2
# activate multiserver_mode add filter for port `5567`
options = {'multiserver_mode': True, 'filter': 5567}
# Define Netgear Client with `port` addresses of all unique Server((4567,5567) in our case). Also, Remember to change following IP address '192.168.x.xxx' with yours, plus activate Request/Reply(`1`) pattern, `recieve_mode`:
client = NetGear(address = '192.168.x.x', port = (4567,5567), protocol = 'tcp', pattern = 1, receive_mode = True, **options)
# Define received frame dictionary
frame_dict = {}
# loop over until Keyboard Interrupted
while True:
try:
# receive data from network
data = client.recv()
# check if data received isn't None
if data is None:
break
# extract unique port address and its respective frame
unique_address, frame = data
# {do something with the extracted frame here}
# get extracted frame's shape
(h, w) = frame.shape[:2]
# update the extracted frame in the received frame dictionary
frame_dict[unique_address] = frame
# build a montage using data dictionary
montages = build_montages(frame_dict.values(), (w, h), (2, 1))
# display the montage(s) on the screen
for (i, montage) in enumerate(montages):
cv2.imshow("Montage Footage {}".format(i), montage)
# check for 'q' key if pressed
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
except KeyboardInterrupt:
break
# close output window
cv2.destroyAllWindows()
# safely close client
client.close()
```
 
### B1. Server-1's End Code:
Open the terminal on System _(a.k.a Server-1)_ with a webcam connected to it and execute the following python code.
:warning: _Remember to replace the IP address in the following code with Client's IP address copied earlier and also copy the unique port address of this system(required by Client to identify this system)._
```python
# import libraries
from vidgear.gears import NetGear
import cv2
# Open suitable video stream (webcam on first index in our case)
stream = cv2.VideoCapture(0)
# activate multiserver_mode
options = {'multiserver_mode': True}
# change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address (4567 in our case) but keep rest of settings similar to Client
server = NetGear(address = '192.168.x.x', port = '4567', protocol = 'tcp', pattern = 1, **options)
# loop over until Keyboard Interrupted
while True:
try:
# read frames from stream
(grabbed, frame) = stream.read()
# check for frame if not grabbed
if not grabbed:
break
# {do something with the frame here}
# send frame to server
server.send(frame)
except KeyboardInterrupt:
break
# safely close video stream
stream.release()
# safely close server
server.close()
```
 
### B2. Server-2's End Code:
Open the terminal on System _(a.k.a Server-2)_ also with a webcam connected to it and execute the following python code.
:warning: _Remember to replace the IP address in the following code with Client's IP address copied earlier and also copy the unique port address of this system(required by Client to identify this system)._
```python
# import libraries
from vidgear.gears import NetGear
import cv2
# Open suitable video stream (webcam on first index in our case)
stream = cv2.VideoCapture(0)
# activate multiserver_mode
options = {'multiserver_mode': True}
# change following IP address '192.168.1.xxx' with Client's IP address and assign unique port address (5567 in our case) but keep rest of settings similar to Client
server = NetGear(address = '192.168.x.x', port = '5567', protocol = 'tcp', pattern = 1, **options)
# loop over until Keyboard Interrupted
while True:
try:
# read frames from stream
(grabbed, frame) = stream.read()
# check for frame if not grabbed
if not grabbed:
break
# {do something with the frame here}
# send frame to server
server.send(frame)
except KeyboardInterrupt:
break
# safely close video stream
stream.release()
# safely close server
server.close() server.close()
``` ```
... ...
......