The network programming course is designed to do what you want, with code + experimental report attached.
Environment configuration
python 3.7.3
pymysql 1.0.2
Tensorflow GPU 2.0.0 (cpu can also be used)
numpy 1.19.2
tk 8.6.10
MySQL 8.0.23
Navicat version
It's not critical. The environment setting is mainly related to tf
code
Click to download the github code
Server
Neural network model required cnn.h5 It can be obtained from other training and can be at the bottom reference From github, I rewrite the prototype.
import socket import pickle import numpy import pymysql from tensorflow import keras # Default tcp mode transmission sk = socket.socket() sk2 = socket.socket() # Binding IP and port ip_port = ('192.168.43.31', 8888) ip_port2 = ('192.168.43.31', 8889) # Binding listening sk.bind(ip_port) sk2.bind(ip_port2) # maximum connection sk.listen(5) sk2.listen(5) #Loading the trained cnn model model=keras.models.load_model("cnn.h5") #Connect to local database con = pymysql.connect(host='localhost', user='root', password='0208', db='client_list', charset='utf8') cursor = con.cursor() log_in = 0 def send_from(arr, dest): view = memoryview(arr).cast('B') while len(view): nsent = dest.send(view) view = view[nsent:] def recv_into(arr, source): view = memoryview(arr).cast('B') while len(view): nrecv = source.recv_into(view) view = view[nrecv:] # Receive data continuously while True: # Prompt information print("Waiting to receive data.......") # Receive data connection object and customer address con2, address = sk2.accept() while True: user = con2.recv(1024).decode() sql = "select password from password where username = '" + user + "'" cursor.execute(sql) #print("searching") password=con2.recv(1024).decode() for i in cursor.fetchall():#Return a tuple #print(i) if password in i: log_in = 1 con2.send(pickle.dumps(log_in)) if log_in == 1: break #Login process conn, address = sk.accept() # Constantly receive messages from customers while True: # Receive client messages if log_in == 1: print('receiving data') data=numpy.zeros(784).reshape(1,28,28,1).astype(float) recv_into(data, conn) #print(data) # Exit command received if data.sum() == 0: print('EXIT') log_in = 0 break rec = model.predict_classes(data)[0] conn.send(pickle.dumps(rec)) # Actively close the connection conn.close()
client
Main function main py
# -*- coding:utf-8 -*- from tkinter import Tk from Window import Window import socket if __name__ == '__main__': win=Tk() ww = 530#Window width setting 530 wh = 430#Window height setting 430 # The server adopts TCP mode, and the client also adopts TCP mode. The default parameter is TCP client = socket.socket() # IP and port to access the server ip_port= ('192.168.43.31', 8888) # Connect host client.connect(ip_port) Window(win,ww,wh,client) win.protocol("WM_DELETE_WINDOW",Window.closeEvent) win.mainloop()
Class window py
# -*- coding:utf-8 -*- from tkinter import * from PIL import Image,ImageDraw import numpy as np import pickle import socket import sys def send_from(arr, dest): view = memoryview(arr).cast('B') while len(view): nsent = dest.send(view) view = view[nsent:] def recv_into(arr, source): view = memoryview(arr).cast('B') while len(view): nrecv = source.recv_into(view) view = view[nrecv:] class Window: def __init__(self,win,ww,wh,client): self.win=win self.ww=ww self.wh=wh self.client=client self.win.geometry("%dx%d+%d+%d" %(ww,wh,500,100)) self.win.title("Handwritten numeral recognition software---by 20180620 Cryptobranchoidea ") self.can=Canvas(self.win,width=ww-130,height=wh-32,bg='white') self.can.place(x=0,y=0) self.can.bind("<B1-Motion>",self.paint) self.entry1=Entry(self.win,width=16) self.entry1.place(x=405,y=200) self.entry2=Entry(self.win,width=16) self.entry2.place(x=405,y=260) self.label1=Label(self.win,text="Identification results:",font=('Microsoft YaHei ',20)) self.label1.place(x=405,y=0) self.label2=Label(self.win,width=6,height=2,text='',font=('Microsoft YaHei ',20), background="white",relief="ridge",borderwidth=10) self.label2.place(x=405,y=50) self.label3=Label(self.win, text="user name:",font=('Microsoft YaHei ',10)) self.label3.place(x=405,y=170) self.label4=Label(self.win, text="password:",font=('Microsoft YaHei ',10)) self.label4.place(x=405,y=230) self.button1=Button(self.win,text="Predict",width=10,height=1,bg='gray',command=self.predict) self.button1.place(x=10,y=wh-30) self.button2=Button(self.win,text="Clear",width=10,height=1,bg='white',command=self.clear) self.button2.place(x=100,y=wh-30) self.button3=Button(self.win,text="Exit", width=10,height=1,bg='white',command=self.exit_) self.button3.place(x=200,y=wh-30) self.button4=Button(self.win,text="Log in", width=10,height=1,bg='white',command=self.log_in) self.button4.place(x=280,y=wh-30) self.image=Image.new("RGB",(ww-130,wh-30),color=(0,0,0))#(0,0,0) indicates a black background self.draw=ImageDraw.Draw(self.image) self.valid_flag = 0 self.client2 = socket.socket() # IP and port to access the server self.ip_port2= ('192.168.43.31', 8889) # Connect host self.client2.connect(self.ip_port2) def log_in(self): user=self.entry1.get().encode() password=self.entry2.get().encode() self.client2.send(user) self.client2.send(password) _data=self.client2.recv(1024) self.valid_flag=pickle.loads(_data) if self.valid_flag == 1: messagebox.showinfo(title='Login successful', message='welcome!') else: messagebox.showwarning(title='Login failed', message='Wrong user name or password!') def paint(self,event): self.x1,self.y1=event.x-12,event.y-12 self.x2,self.y2=(self.x1+24),(self.y1+24) self.can.create_rectangle(self.x1, self.y1, self.x2, self.y2, fill="black") self.draw.rectangle(((self.x1,self.y1),(self.x2,self.y2)),(255,255,255))#(255255255) indicates white words def predict(self): if self.valid_flag== 0 : messagebox.showwarning(title='warning', message='Please log in first') else: if np.array(self.image).sum()==0:#It is detected that the prediction has not been handwritten, and the prediction result is empty self.display('') else: self._image=self.image.resize((28,28),Image.ANTIALIAS).convert('L') self._image=np.array(self._image).reshape(1,28,28,1).astype(float)#shape is (- 1,28,28,1) during training #self.rec=self.model.predict_classes(self._image.astype(float))[0] send_from(self._image, self.client) _data = self.client.recv(1024) data = pickle.loads(_data) #self.client.send(pickle.dumps(self._image)) self.display(data)#Display forecast results self.draw=ImageDraw.Draw(self.image) def clear(self): self.can.delete("all") self.image=Image.new("RGB",(self.ww-130,self.wh-30),(0,0,0))#(0,0,0) indicates a black background self.draw=ImageDraw.Draw(self.image) self.display('') def display(self,string): self.label2=Label(self.win,width=6,height=2,text=string,font=('Microsoft YaHei ',20), background="white",relief="ridge",borderwidth=10) self.label2.place(x=405,y=50) def exit_(self): if self.valid_flag ==1: _image=np.zeros(784).reshape(1,28,28,1).astype(float) send_from(_image, self.client) self.client2.close() self.win.destroy() def closeEvent(): Window.win.destroy() sys.exit()
Experimental report
1, Overall function description
1. Function overview
Neural networks in artificial intelligence are being more and more widely used in various fields of society. Using artificial neural network to process data in stand-alone mode not only needs to embed the huge trained neural network model into the program, but also needs to load the neural network into memory every time the program is started, which is time-consuming. Therefore, taking mnist data set as an example, we originally wrote a set of handwritten numeral neural network recognition program based on client server mode of LAN.
2. General functional drawing
Client Yellow & server green
3. Flow chart of each sub function
3.1 server initialization
Include must include: socket, numpy, pickle, pymysql, and keras in tensorflow.
tcp protocol binds and listens to two ports: tcp mode, which binds the server-side ip address and two ports (one is used to log in and query the database, and the other is used to send recognized handwritten digits) to bind and listen.
Load the neural network training model: load the trained through the keras package h5 neural network model.
Link to local database: connect to the local database through pymysql and obtain the database cursor.
Set login status to No: if no, the client cannot send detection information through another port. Pop up at the same time.
3.2 client initialization
Include packages: socket, numpy, pickle, tkinter, PIL.
tcp protocol binding listens to two ports: tcp mode, which connects the two ports of the server ip address (one is used to log in and query the database, and the other is used to send recognized handwritten digits). If successful, no error will be reported.
Create visual interface: create a visual interface through tkinter, including function buttons, prompt information, text boxes, etc. Set the width and height of the visual program interface and bind various functions.
Set login status to No: if no, the client cannot send detection information through another port. Pop up at the same time.
3.3 user login + database query
See II. Description of database and III. description of communication for details
3.4 interactive drawing (client paint function, clear function)
When the mouse falls, moves and refreshes: during initialization, bind the canvas canvas to be valid when left clicking. When left clicking, call the paint function to draw a black box on the canvas continuously according to the landing point of the captured mouse event.
When the Clear button is pressed, the canvas is cleared and the label2 prediction result is also cleared.
3.5 recognition and detection of handwritten digits through neural network (client predict function)
See description of communication section III for detailed data flow diagram
3.6 exit and sever links (client exit function)
See description of communication section III for detailed data flow diagram
2, Database function description
1. Database overview
The database is used to store user name and password information. MySQL database is selected as the database, which is used on the server, and the client does not call the database. Database creation (user information entry) and visualization using Navicat software, calling database in python, using pymysql to expand functions in packages.
2. Database E-R diagram
3. Data dictionary
Field name | data type | Default value | Non null allowed | Auto increment | remarks |
---|---|---|---|---|---|
username | string | – | NO | 0 | user name |
password | string | – | NO | 0 | password |
4. Data flow diagram
3, Description of communication part
1. Communication security
In order to ensure communication security, we have made the following considerations during program development:
The database is arranged as the local database of the server, rather than the client accessing the server database through port 3306. The server accesses the database locally and organizes the database network connection, which can ensure that the server user name and password are not leaked.
The login success flag is set on both the client and the server. After receiving the information sent by the client through port 1 (8888 in the program), the server returns the correct flag after finding the correct password in the database, and sets the login flag of the client on the server to correct; If the password is found to be wrong, the error flag will be returned. The client receives a flag followed by a login success flag set according to the flag. When and only when the server flag is correct, it starts to receive data from port 2 (8889 in the program). When the client login flag is incorrect, the prediction will not send numpy array to the server through port 2. At this time, clicking the exit button function will not send an empty array to the server to disconnect the link, but directly disconnect the link of port 1 (because the link of port 2 has not been established at this time). At the same time, the login success flag is set to prevent the client from sending the data to be identified to the server without login.
2. Communication mode
Networking: the client and server are connected to the mobile hotspot LAN. In the experiment, the IP address of the server is 192.168.43.31. Two ports are used, in which one port (8888) is used for login message confirmation, and the other port (8889) is used for sending and returning identification information of numpy array to be identified. The database adopts local database and is not connected to the network. (however, we have realized the connection of database in LAN. We do not use network database, just to ensure communication security.
Communication protocol: it adopts the communication protocol encapsulated by socket package in python. Socket provides TCP and UDP protocol sending methods. This program uses TCP protocol to send data. Sending data needs to be sent in byte stream (byte class). This program uses pickle package to package int class and send short messages; For the numpy array of 28*28 float type exceeding the length limit of TCP message sent, the method of reading and sending by memory is adopted. For strings (user name / password), use the python string class's own encode() and The decode() method is converted to a byte stream.
4, Testing
1. Function test
The procedure is generally complete, and the defects are as follows:
(1) You must press the exit key in the program to exit, but you cannot press the X in the upper right corner to exit. Because the link establishment is encapsulated inside the class, the link cannot be called when the form is destroyed by pressing x, so pressing x will cause the unexpected interruption of the link.
(2) When you are not logged in, pressing exit to exit will cause the link for login to be accidentally disconnected, and the link cannot be established next time you log in.
Possible improvement methods: move the link establishment steps outside the class, or break the link in the subclass by inheritance, and use the form structure as the parent class.
2. Efficiency test
Due to the limited number of notebooks, the program has only tested the connection of one laptop. It is expected that there will still be bug s when connecting multiple clients.
We preprocess the handwritten digits to be recognized at the client, compress the 160X160 array into a 28 * 28 array that needs to be input into the neural network, and then send it, which greatly improves the efficiency of data transmission.
Others want to say
The school's network programming course requires the group to think of a topic and do it by themselves. It was written in ddl on the last day. In addition to the UI, as long as you can send data through the network (socket). Remember to turn off the firewall. mysql database should be built by yourself. Just change the server statement. There are many bug s, too lazy to fix~