socket Network Programming (TCP/IP, UDP) in Python

Keywords: socket network encoding Programming

Socket is a basic component of network programming. Sockets are basically "information channels" between programs with two endpoints. Programs may be distributed on different computers, sending information to each other through sockets. Sockets include two: server sockets and client sockets. After creating a server socket, let it wait for a connection. So it listens at a network address (a combination of ip addresses and ports) until there is a client socket connection. When the connection is complete, the two can interact.

Socket socket
A socket is an instance of the socket class in the socket module. Its instantiation requires three parameters:
The first parameter is the address family, which defaults to socket. AF_INET (specifying the use of IPv4 protocol)
The second parameter is the stream, which defaults to socket. SOCK_STREAM (specifying the flow-oriented TCP protocol), or the datagram socket.SOCK_DGRAM socket.
The third parameter is the protocol used, which defaults to 0.

import socket
# s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# Here we all use the default values.
s=socket.socket()

After the server socket uses the bind method, it calls the listen method to listen for a specific address.

s.bind(('127.0.0.1',9999))#Binding addresses and ports
s.listen(5)#The server starts to listen for client connections. The number of connections allowed to queue is 5, which is usually set at 5.

Port is self-designed, IP I use is the local IP address, of course, if the server program on other hosts, it will be replaced by other ip. Port numbers below 1024 are generally restricted for use in standard services, such as port 80 for web services.

After the server socket starts listening, it quietly waits for the client to connect. This step is done using the accept method, which blocks the connection to the client. This method returns a tuple in the form of (client,address), client is a client socket, and address is a tuple in the form of (host,port). After processing the connection with the client, the server calls the accept method again and waits for the next connection. Usually, this process is implemented in an infinite loop.

while True:
    #Accept a client connection
    sock,addr=s.accept()#addr is a tuple ('127.0.0.1', port)
    #Next, you can create a new thread to handle the current client connection

Now let's see how the client connects to the server. The client socket connects to the server using the connect method. The address used in the connect method must be the same as the address bound by the server in the bind method.

import socket
c=socket.socket()#Create client sockets
c.connect(('127.0.0.1',9999))#Connect servers

Sockets have two methods: send and recv, which are used to send and receive data, respectively. Send method takes string as parameter, recv takes a maximum number of bytes as parameter, if not sure, 1024 is better.

c.send('hello,I am xxx!')
c.recv(1024)

After introducing the basic content, let's take a complete example. The client connects to the server. The client sends a set of names XXX to the server, and then the server replies to hello, xxx!.

#The server
import socket
import threading
#Processing client requests
def tcplink(sock,addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send('welcome!')
    while True:
        data=sock.recv(1024)
        if data=='exit' or not data:
            break;
        sock.send('hello %s' % data)
    sock.close()
    print('Connection from %s:%s closed' % addr)

s=socket.socket()
s.bind(('127.0.0.1',9999))#Binding addresses and ports
s.listen(5)
print('serve is waiting connect.....')
while True:
    sock,addr=s.accept()
    #Create new threads to handle each client connection
    #target=tcplink represents which function the new thread will run
    #args=(sock,addr) represents the parameters passed to this method
    t=threading.Thread(target=tcplink,args=(sock,addr))
    #Start this thread
    t.start()
#Client
import socket
import threading
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#Establish connection
s.connect(('127.0.0.1',9999))
data=s.recv(1024)
print(data)
for i in ['zhangkang','jack','tom']:
    s.send(i)
    data=s.recv(1024)
    print(data)
s.send('exit')
s.close()

TCP establishes reliable connections, while UDP is connectionless and unreliable. When using UDP, you only need to know the ip and port of the target host, and then send it directly, whether it can reach or not is not certain.
With TCP types, server sockets need to be instantiated first and then bound to addresses.

#Here the second parameter selection datagram
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Binding ports:
s.bind(('127.0.0.1', 9999))

But instead of calling the listen() method, the server receives the client's data directly.

while True:
    # Receiving data:
    data, addr = s.recvfrom(1024)
    print('Received from %s:%s' % addr)
    s.sendto('Hello, %s!' % data, addr)

The recvfrom() method returns the data and the address and port of the client, so that when the server receives the data, it can send the data to the client with UDP by calling sendto().

When the client uses UDP, it still creates a UDP-based Socket first, and then sends data directly to the server through sendto() without calling connect():

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in ['zhangkang', 'jack', 'tom']:
    # Send data:
    s.sendto(data, ('127.0.0.1', 9999))
    # Receiving data:
    print s.recv(1024)
s.close()

Receiving data from the server still calls the recv() method.

Simple Chat Room Program

Here I wrote a simple chat room-like program, without using a graphical interface, all messages are displayed in the console.

#The server
# -*- encoding: utf-8 -*-
import socket
import threading

def tcplink(sock,addr):
    print('[%s:%s] is online...' % addr)
    while True:
        try:
            data=sock.recv(1024)
        except:
            socket_set.remove(sock)
            print('[%s:%s] is down!' % addr)
            break
        if data=='exit' or not data:
            socket_set.remove(sock)
            sock.close()
            print('[%s:%s] is down!' % addr)
            break
        else:
            list1=[]
            for i in socket_set:
                if i!=sock:
                    list1.append(i)
            for i in list1:
                i.send(data)

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
socket_set=set()#Used to save each socket object
s.bind(('127.0.0.1',9999))#Binding addresses and ports
s.listen(5)
print('serve is waiting connect.....')
while True:
    #Accept a client connection
    sock,addr=s.accept()#addr is a tuple ('127.0.0.1', port)
    socket_set.add(sock)#Add socket objects to collections
    #Create new threads to handle TCP connections
    t=threading.Thread(target=tcplink,args=(sock,addr))
    t.start()
#Client
# -*- encoding: utf-8 -*-
import socket
import threading

name=raw_input('input you name:')
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#Establish connection
s.connect(('127.0.0.1',9999))
def rec_message():
    while True:
        try:
            data=s.recv(1024)
            print('\r['+data+']')
        except:
            break

t=threading.Thread(target=rec_message)
t.start()
while True:
    st=raw_input()
    if st=='exit':
        s.send(st)
        s.close()
        break
    s.send(name+":"+st)

Clients go offline one by one

Posted by sader on Mon, 07 Jan 2019 00:21:11 -0800