Since the BeagleBone Black is driven by Debian OS, it is possible to use the BeagleBone as an “intellectual” node which will transfer/receive data being measured to/from other computers over a TCP/IP network. In this communication, at least two network
applications will be involved.
One of these should be a “TCP client” which send data to or receive data from the other application running as a “TCP server”. Usually, the TCP client and TCP server are running on different physical computers, although both can be launched on the same host using a
“loopback” interface with an IP address 127.0.0.1.
Communications between TCP/IP network applications are implemented using sockets. A socket is a communication mechanism that allows client/server systems to be developed either locally, on a single machine, or across networks. Sockets are the endpoints of a bidirectional communication channel. Sockets may communicate within the same process, between processes on the same machine, or between processes on different computers .Many Linux functions such as printing, connecting to databases, and serving web pages as well as network utilities such as rlogin for remote login and ftp for file transfer usually use sockets to communicate. The socket mechanism can implement multiple clients attached to a single server.
In this section, we will discuss two examples. The first will illustrate the case when data are sent from the TCP client to the TCP server. The second example will show how the TCP client can receive data from the TCP server. Both TCP server and TCP client will be running on the same PC (the BeagleBone Black) using the “loopback” interface with an IP address 127.0.0.1.
The data will be taken from pins P8.10 – P8.17 of the BeagleBone Black (the source code for this case has been discussed earlier).
The client side of a socket-based system is very simple and straightforward. The client creates a socket by calling the socket() function. This is followed by the connect() function to establish a connection with the TCP server by using the server’s listening socket. Once established, sockets can be used like low-level file descriptors, providing two-way data communications. The data can be transferred from the TCP client to the TCP server using the send() function. To receive data from the server the recv() function can be used.
The next source code (Listing 5) represents the simple TCP client application which will transfer data to the TCP server. For the sake of brevity, error checking is omitted.
However, in production code you should always check for error returns unless there is a very good reason to omit this check.
Listing 5.
import Adafruit_BBIO.GPIO as GPIO import socket
import threading import array import time
QXX = [“P8_17”,“P8_16”,“P8_15”,“P8_14”,“P8_13”,“P8_12”,“P8_11”,“P8_10”]
L1 = [0,0,0,0,0,0,0,0]
tmp = 0 port = 7777 Done = 0
GPIO.setup(“P8_10”, GPIO.IN) # D0 GPIO.setup(“P8_11”, GPIO.IN) # D1 GPIO.setup(“P8_12”, GPIO.IN) # D2 GPIO.setup(“P8_13”, GPIO.IN) # D3 GPIO.setup(“P8_14”, GPIO.IN) # D4 GPIO.setup(“P8_15”, GPIO.IN) # D5 GPIO.setup(“P8_16”, GPIO.IN) # D6 GPIO.setup(“P8_17”, GPIO.IN) # D7
class InpDataThread(threading.Thread):
def run(self):
global tmp global port global Done
cnt = 0
while cnt < 10:
tmp = 0
for i in range(len(QXX)):
L1[i] = GPIO.input(QXX[i]) for i in range(len(L1)):
tmp |= L1[i] << len(L1)-1-i
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = socket.gethostname()
s.connect((host, port))
s.send(str(cnt+1) +”: Bits D7-D0 on port P8: ” + bin(tmp)) s.close()
cnt = cnt + 1 time.sleep(5) Done = 1
thRead = InpDataThread() thRead.start()
while Done == 0:
continue thRead.join()
This code is mostly known for us except the section responsible for the network communication. This is shown below:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = socket.gethostname()
s.connect((host, port))
s.send(str(cnt+1) +”: Bits D7-D0 on port P8: ” + bin(tmp)) s.close()
First, we create a socket (variable s) using the socket.socket() function available in the
socket module. Then the program obtains the local machine name of the computer where the TCP client should be connected to. This is done by the
host = socket.gethostname()
function.
To connect to the TCP server we should call the connect(), passing address host and port as the parameters to this function:
s.connect((host, port))
Each server or client should use one or more ports. A port may be identified by a number, a string containing a number, or the name of a service.
The send() function that follows transfers the message to the TCP server. Finally, the socket is closed by invoking the close() function.
Let’s look at how to develop a TCP server application.
First, the server application creates a socket, using the socket() function the socket
module. Next, the server process gives the socket a name (host and port) by invoking the bind() function.
The server application then waits for a client to connect to the named socket. The listen() function creates a queue for incoming connections. The server can accept them using the accept() function.
When the server calls accept(), a new socket is created that is distinct from the named socket. This new socket is used solely for communication with this particular client. The named socket remains for further connections from other clients. If the server code is written appropriately, it can take advantage of multiple connections.
For the simple TCP server, further clients wait on the listen queue until the server is ready again.
The TCP server source code running on the same BeagleBone host is shown in Listing 6.
Listing 6.
import socket # import the socket module
srv = socket.socket() # Create a socket object host = socket.gethostname() # Get local machine name
port = 7777 # Assign a port to receive incoming requests addr = (host, port)
srv.bind(addr)
srv.listen(5)
print “TCP Server is waiting for incoming requests on port 7777…”
while True:
c, caddr = srv.accept() msg = c.recv(256) print msg
c.close()
The program code creates the socket by executing the statement
srv = socket.socket()
The socket() function returns a descriptor in the variable srv – it can be used for accessing the socket. Then the local machine name is obtained by invoking the
host = socket.gethostname()
function. The value returned by this function is saved in the host variable. The TCP
server also needs the port (we use 7777). Both the host and port are needed for making the socket available for use by application. The addr variable makes up the address needed for the socket from the host and port:
addr = (host, port)
Then the program code invokes the bind() function which assigns the address specified in the addr variable to the unnamed socket associated with the file descriptor srv.
To accept incoming connections on a socket, a server program must create a queue to store pending requests. It accomplishes this by using the listen() function.
After creating the listening socket, the server enters the endless while() loop waiting for incoming requests on port 7777. When a new request comes, the TCP server creates a working connection (socket) to the particular client by invoking the accept() function:
c, caddr = srv.accept()
The accept() function returns the client connection ID (variable c) and the address assigned to a working socket (variable caddr). When done, all data are passed through this connection. In our case, the TCP server receives data from the client by invoking the recv() function:
msg = c.recv(256)
Then data obtained (variable msg) is output to the console, the working socket is closed by invoking the (close() function) and the while() loop continues.
The TCP server provides the following output:
root@beaglebone:/# python TCPServer_Read8bit.py
TCP Server is waiting for incoming requests on port 7777…
1: Bits D7-D0 on port P8: 0b11101001 2: Bits D7-D0 on port P8: 0b11101001 3: Bits D7-D0 on port P8: 0b11101001 4: Bits D7-D0 on port P8: 0b11101001 5: Bits D7-D0 on port P8: 0b11001001 6: Bits D7-D0 on port P8: 0b11101001 7: Bits D7-D0 on port P8: 0b11001000 8: Bits D7-D0 on port P8: 0b11001000 9: Bits D7-D0 on port P8: 0b11001000 10: Bits D7-D0 on port P8: 0b11001000