[Python] using the TCP protocol chat server and client (socket)

This project uses Socket create a TCP connection to achieve real-time chat between server and client.
Background:
Server: Ali cloud server Ubuntu 16.04
Local: Win 10

Environment:
server: Python 3.5.2
Local: Python 3.6.5

We need to use the module:
socket, Threading

Here to put TCP programming, client and server processes as well as their data exchange process between them.
Here Insert Picture Description

Client code

The client sends information to the server to play, to accept the function information.

'''
created on April 5 2019 20:23

@author:lhy
'''
#客户端代码
import socket
import threading

#接受服务器返回的数据的函数,开启线程时使用
def recvlink(client):
    while True:
        msg=client.recv(1024)
        print('Ubuntu say: '+msg.decode('utf-8'))

def main():
    #创建ipv4的socket对象,使用TCP协议(SOCK_STREAM)
    client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    #设置服务器ip地址,注意应该是服务器的公网ip
    host='112.74.50.102'
    #设置要发送到的服务器端口,需要在云服务器管理界面打开对应端口的防火墙
    port=1234

To open ports in the firewall server management interface you can use socket by 公网IP+端口号sending data to a designated port for the server. Specific operations as follows (my Ali cloud server):
The first step Click Add Rules:
Here Insert Picture Description
Part II, set the required open ports:
Here Insert Picture Description
The following code is then written above:

    #建立TCP协议连接,这时候服务器就会监听到到连接请求,并开始等待接受client发送的数据
    client.connect((host,port))

    #建立连接后,服务器端会返回连接成功消息
    start_msg=client.recv(1024)
    print(start_msg.decode('utf-8'))

For clients to input and receive server messages do not conflict, the creation of a new thread here to receive messages returned by the server.

    #开启一个线程用来接受服务器发来的消息
    t=threading.Thread(target=recvlink,args=(client,))
    t.start()

    #发送消息
    while True:
        #输入要发送的信息
        sendmsg=input()
        #向服务器发送消息
        client.send(sendmsg.encode('utf-8'))
        if sendmsg=='quit':
            break
    #结束时关闭客户端
    client.close()

if __name__ == '__main__':
    main()

Server-side code

Server-side play a listening port, receive information, reply to the role of information.
code show as below:

'''
created on April 5 2019 20:32

@author:lhy
'''
#服务器端
import socket
import threading


#接受客户端消息函数,开启新线程时使用
def recv_msg(clientsocket):
    while True:
        # 接受客户端消息,设置一次最多接受1024字节的数据
        recv_msg = clientsocket.recv(1024)
        # 把接收到的东西解码
        msg = recv_msg.decode('utf-8')
        # 如果用户输入了quit,就退出此对话
        if msg == 'quit':
            exit(0)
        print('Win10 say: ' + msg)

Note that we listen to bind address and port. Since the server may have multiple network cards (such as routers), it can be bound to an IP address of a network card that is on the IP network, but can also be used 0.0.0.0to bind to all network addresses, can also be used 127.0.0.1to bind to local address. But 127.0.0.1it is a special IP address, local address representation, if bound to this address, the client must be running in order to connect the machine, that is, outside the computer can not connect to come. For projects is concerned, can not be used 127.0.0.1as a host, use 0.0.0.0or internal server IP address can be, I am here to use the network server's IP address.

def main():
    #创建服务器端socket对象 ipv4 + TCP协议,和客户端一样
    socket_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

   
    #host='0.0.0.0'# 这个host也行
    host='172.17.23.96'
    #设置被监听的端口号,小于1024的端口号不能使用,因为他们是Internet标准服务的端口号
    port=1234

    #绑定地址
    socket_server.bind((host,port))
    #设置最大监听数,也就是最多可以同时响应几个客户端请求,一般配合多线程使用
    socket_server.listen(5)
    #等待客户端连接,一旦有了连接就立刻向下执行,否则等待在此
    #accept()函数会返回一个元组,第一个元素是客户端socket对象,第二个元素是客户端地址(客户端的 ip地址+端口号)
    clientsocket,addr=socket_server.accept()
	# 有了客户端连接后才能执行以下代码
    
    #我们先向客户端发送表示连接成功的消息
    clientsocket.send('你现在已经连接上了服务器啦,我们来聊天吧!'.encode('utf-8'))

    # 和客户端一样开启一个线程接受客户端的信息
    t=threading.Thread(target=recv_msg,args=(clientsocket,))
    t.start()

    # 发送消息
    while True:
        reply=input()
        clientsocket.send(reply.encode('utf-8'))

    clientsocket.close()
if __name__=='__main__':
    main()

The net effect:
full dialogue retarded. . .
Here Insert Picture Description

All the code (py file with the unit)

Client

File name: client.py

'''
created on April 5 2019 20:23
filename: client.py
@author: lhy
'''
#客户端代码
import socket
import threading

#接受服务器返回的数据的函数
def recvlink(client):
    while True:
        msg=client.recv(1024)
        print('Ubuntu say: '+msg.decode('utf-8'))

def main():
    #创建ipv4的socket对象,使用TCP协议(SOCK_STREAM)
    client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    #设置服务器ip地址,注意应该是服务器的公网ip
    host='112.74.50.102'
    #设置要发送到的服务器端口,需要在云服务器管理界面打开对应端口的防火墙
    port=1234

    #建立TCP协议连接,这时候服务器就会监听到到连接请求,并开始等待接受client发送的数据
    client.connect((host,port))

    #建立连接后,服务器端会返回连接成功消息
    start_msg=client.recv(1024)
    print(start_msg.decode('utf-8'))

    #开启一个线程用来接受服务器发来的消息
    t=threading.Thread(target=recvlink,args=(client,))
    t.start()

    #发送消息
    while True:
        #输入要发送的信息
        sendmsg=input()
        #向服务器发送消息
        client.send(sendmsg.encode('utf-8'))
        if sendmsg=='quit':
            break
    #结束时关闭客户端
    client.close()

if __name__ == '__main__':
    main()

Service-Terminal

File name: server.py

'''
created on April 5 2019 20:32
filename: server.py
@author: lhy
'''
#服务器端
import socket
import threading


#接受客户端消息函数
def recv_msg(clientsocket):
    while True:
        # 接受客户端消息,设置一次最多接受1024字节的数据
        recv_msg = clientsocket.recv(1024)
        # 把接收到的东西解码
        msg = recv_msg.decode('utf-8')
        # 如果用户输入了quit,就退出此对话
        if msg == 'quit':
            exit(0)
        print('Win10 say: ' + msg)

def main():
    #创建服务器端socket对象 ipv4 + TCP协议,和客户端一样
    socket_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 注意注意注意,我们要绑定监听的地址和端口。服务器可能有多块网卡,可以绑定到某一块网卡的IP地址上,也可以用0.0.0.0绑定到所有的网络地址
    # 还可以用127.0.0.1绑定到本机地址。127.0.0.1是一个特殊的IP地址,表示本机地址,如果绑定到这个地址,客户端必须同时在本机运行才能连接,也就是说,外部的计算机无法连接进来。
    # 这个程序中host使用'0.0.0.0'或服务器内网ip地址都可以,我这里就使用了内网ip地址
    #host='0.0.0.0'
    host='172.17.23.96'
    #设置被监听的端口号,小于1024的端口号不能使用,因为他们是Internet标准服务的端口号
    port=1234

    #绑定地址
    socket_server.bind((host,port))
    #设置最大监听数,也就是最多可以同时响应几个客户端请求,一般配合多线程使用
    socket_server.listen(5)
    #等待客户端连接,一旦有了连接就立刻向下执行,否则等待
    #accept()函数会返回一个元组,第一个元素是客户端socket对象,第二个元素是客户端地址(ip地址+端口号)
    clientsocket,addr=socket_server.accept()

    # 有了客户端连接后之后才能执行以下代码,我们先向客户端发送连接成功消息
    clientsocket.send('你现在已经连接上了服务器啦,我们来聊天吧!'.encode('utf-8'))

    # 和客户端一样开启一个线程接受客户端的信息
    t=threading.Thread(target=recv_msg,args=(clientsocket,))
    t.start()


    # 发送消息
    while True:
        reply=input()
        clientsocket.send(reply.encode('utf-8'))

    clientsocket.close()
if __name__=='__main__':
    main()

Data sent by the client to the server time, addr server receives the public IP address of the client, but when the server should listen listening IP address within the server network. When the client and server data exchange, data packets to send over the LAN to the external network router, not the customer through the external network to forward data packets from the device and the server displays the IP address of the client outside the network, and the computer display terminal by the router automatically (or manually) assign an IP address sub-LAN. We found that the client receives is sent to the server-side data packets, different router port number of the client application under a different process for packet distribution. Similarly, the data allocation process performed when the server receives the client packet as well.

Published 61 original articles · won praise 16 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_41427568/article/details/89049194