Enable the server to accept connections |
|
Now that we understand the importance of the socket module, let's look at how to build servers and clients in Python.
What is a server
A server is either a program, a computer, or a device specifically used to manage network resources. The server can be on the same device or computer, locally connected to other devices and computers, or even remotely. There are various types of servers such as database servers, web servers, print servers, etc.
Servers usually use socket.socket(), socket.bind(), socket.listen(), etc. to establish connections and bind to clients. Now let us write a program to create a server.
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1234))
#port number can be anything between 0-65535(we usually specify non-previleged ports which are > 1023)
s.listen(5)
while True:
clt,adr=s.accept()
print(f"Connection to {adr}established")
#f string is literal string prefixed with f which
#contains python expressions inside braces
clt.send(bytes("Socket Programming in Python","utf-8 ")) #to send info to clientsocket
Copy after login
The first necessary condition for creating a socket is to import the relevant modules. Then use the socket.socket() method to create a server-side socket.
AF_INET refers to the address from the Internet, which requires a pair (host, port), where the host can be the URL or address of a specific website, The port number is an integer. SOCK_STREAM is used to create the TCP protocol.
bind() method accepts two parameters as a tuple (host, port). It should be noted here that it is best to use a 4-digit port number, because lower port numbers are usually occupied or reserved by the system. The listen() method allows the server to accept connections, and 5 is a queue for multiple connections accepted at the same time. The minimum value that can be specified here is 0, and if no parameters are specified, the default appropriate parameters are used.
The while loop allows forever to accept connections, clt and adr are the client objects and addresses, the print statement just prints out the address and port number of the client socket, and finally, clt.send is used to send bytes Send data to the unit.
Now that our server is set up, let's move on to the client.
What is a client
A client is a computer or software that receives information or services from a server. In the client-server model, the client requests services from the server. The best examples are web browsers such as Google Chrome, Firefox, etc. These web browsers request the web server to provide the required web pages and services based on the user's instructions. Other examples include online gaming, online chat, etc.
Now, let us see how to write a client program in the Python programming language:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
msg=s.recv(1024)
print(msg.decode("utf-8"))
Copy after login
First, still import the socket module, and then create the socket as you did when creating the server. Then to create a connection between the client and server, you need to use the connect() method by specifying (host, port).
Note: When the client and server are on the same computer, you need to use gethostname. (LAN–localip/WAN–publicip)
Here, the client wants to receive some information from the server, for this we need to use the recv() method, the information is stored in another variable msg . It is important to note that the information being transferred will be in bytes, and in the client of the above program, a maximum of 1024 bytes (buffer size) can be received in one transfer. This can be specified as any number depending on the amount of information being transferred.
Finally, decode and print the message being transmitted.
Now that we have seen how to create client-server programs, let's look at how they need to be executed.
Client-server interaction
To execute these programs, you need to open the command program, enter the folder where the client and server programs are created, and then type:
py server.py #这里,server.py 是服务器的文件名
Copy after login
No surprises The server starts running
To execute the client, you need to open another cmd window and type:
pyclient.py
Copy after login
## below Let us reduce the buffer size to 7 and see what the same program would look like As shown in the figure, after 7 bytes have been transferred, the connection is terminated. In fact, this is a problem because we have not received the complete information, but the connection was closed early. Let us solve this problem. Multiple communicationIn order to continue the connection before the client receives the complete message, we can use a while loopimport socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
while True:
msg=s.recv(7)
print(msg.decode("utf-8"))
Copy after login
After this modification, each transmission will be 7 words section to receive the complete message. But this brings up another problem, the connection never terminates, you never know when it will terminate. Also, what if we don't actually know how big the message or information the client will receive from the server is. In this case, we need to continue to improve the code complete_info=''
while True:
msg = s.recv(7)
if len(msg)<=0:
break
complete_info += msg.decode("utf-8")
print(complete_info)
Copy after login
On the server side, use the close() method as shown below: clt.close()
Copy after login
The output is as follows: 程序会检查信息的大小,并将其打印到一次两个字节的缓冲区中,然后在完成连接后关闭连接。
传输 Python 对象
目前为止我们仅仅掌握了传递字符串的方法,但是,Python 中的 Socket 编程也允许我们传输 Python 对象。这些对象可以是集合、元组、字典等。要实现这一点,需要用到 Python 的 pickle 模块。
Python pickle模块
当我们实际序列化或反序列化 Python 中的对象时,就会使用到 Python pickle 模块。让我们看一个小例子
import pickle
mylist=[1,2,'abc']
mymsg = pickle.dumps(mylist)
print(mymsg)
Copy after login
Output:
b’x80x03]qx00(Kx01Kx02Xx03x00x00x00abcqx01e.’
Copy after login
在上面的程序中,mylist是使用pickle模块的dumps()函数序列化的。还要注意,输出以b开头,表示它已转换为字节。在 socket 编程中,可以实现此模块以在客户端和服务器之间传输 python 对象。
如何使用 pickle 模块传输 Python 对象
当我们将 pickle 与 socket 一起使用时,完全可以通过网络传输任何内容。
先来看看服务端代码
Server-Side:
import socket
import pickle
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 2133))#binding tuple
s.listen(5)
while True:
clt , adr = s.accept()
print(f"Connection to {adr}established")
m={1:"Client", 2:"Server"}
mymsg = pickle.dumps(m)#the msg we want to print later
mymsg = {len(mymsg):{a}}"utf-8") + mymsg
clt.send(mymsg)
Copy after login
这里,m是一个字典,它基本上是一个需要从服务器发送到客户端的 Python 对象。这是通过首先使用dumps()序列化对象,然后将其转换为字节来完成的。
现在,让我们记下客户端:
Client-Side:
import socket
import pickle
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2133))
while True:
complete_info = b''
rec_msg = True
while True:
mymsg = s.recv(10)
if rec_msg:
print(f"The length of message = {mymsg[:a]}")
x = int (mymsg[:a ] )
rec_msg = False
complete_info += mymsg
if len(complete_info)-a == x:
print("Recieved the complete info")
print(complete_info[a:])
m = pickle.loads(complete_info[a:])
print(m)
rec_msg = True
complete_info = b''
print(complete_info)
Copy after login
第一个while循环将帮助我们跟踪完整的消息(complete_info)以及正在使用缓冲区接收的消息(rec_msg)。
然后,在接收消息时,我们所做的就是打印每一位消息,并将其放在大小为10的缓冲区中接收。此大小可以是任何大小,具体取决于个人选择。
然后如果收到的消息等于完整消息,我们只会将消息打印为收到的完整信息,然后使用loads()反序列化消息。
输出如下: