快速上手python socket编程

之前在编写四层发现的代码时都是使用TCP/UDP协议, 但是看了很多的代码都是用socket来完成的,所以就 来学习一下socket。

 

什么是socket

网络中的两台主机之间进行通信,本质上是主机中所 运行的进程之间的通信,两个进程如果需要进行通信 ,最基本的前提是每一个进程要有一个唯一的标识。

在本地进程通信中可以使用PID来唯一标识一个程, 但PID在 本地是唯一,可以用 "IP地+ 协议+端口号" 来组成唯一标识的网络进程,这就是socket。

无论使用何种网络协议,最本质上都是在进行数据 的收发,发和收,这两个动作就是socket处理数据 的主要方式。

socket的工作流程

socket 采用C/S 模式,分为服务端和客户端
服务端数据处理流程
创建socket -> 绑定到地址和端口 -> 等待连接 -> 开始通信-> 关闭连接
客户端数据处理流程
创建socket -> 等待连接 -> 开始通信-> 关闭连接
客户端没有绑定地址和端口,是由于客户端进程采用的是随机端口,当客户端要去连接目标时,会由系统自定分配一个端口号和自身ip地址去组合
 

socket_tcp_udp_client_service.py

#!/usr/bin/env python3
#coding=utf-8
import sys
import socket
import time 
import os
import threading


ServerIp='192.168.1.1'
ServerPort=9999


def tcp_client_run(): 
    global ServerIp
    global ServerPort
    print("tcp socket client connect to: ",ServerIp, ServerPort)
    myServerPort=int(ServerPort)
    #创建一个socket的类,socket.AF_INET指的是IPV4,SOCK_STREAM指的是TCP协议,UDP协议对应socket_DRAM
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #连接PC服务器的端口,参数是(IP/域名,端口)
    ServerPort_=(ServerIp,myServerPort)
    # connect_ex是connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
    s.connect_ex(ServerPort_)
     
    #接受服务器的消息,限制接受大小为1kb=1024b=128KB
    while True:
        try:
            #接受消息,并打印,解码用utf-8
            print("Local:OK?")
            print(s.recv(1024).decode('utf-8'))
            time.sleep(1)
            #发送消息,注意用二进制的数据传输,因为发送的实际是一个数据流
            data=(('Client'.encode('utf-8')))
            s.send(data)
        except:
            break
    print("Connection is closed by Server")


 
#定义一个接受和发送数据的函数,5次发送后即在服务器端强行关闭连接。
def tcplink(sock,addr):
    global ServerIp
    print("Accept the new connection from %s:%s"%addr)
    sock.send(b"Welcome!Here is the Sever ")
    n=int(5)
    while n>0:
        data=sock.recv(1024)
        time.sleep(1)
        sock.send(('Server==>I have heard you.{:s}:{:d},{:d} talks remaining\n'.format(addr[0],addr[1],n-1)).encode('utf-8'))
        sock.send(('Server==>You said:{:s}\n'.format(data.decode('utf-8'))).encode('utf-8'))
        n-=1
    sock.close()
    print('Connection from %s is close.'%addr[0])
 
 
def tcp_service_run(): 
    global ServerIp
    global ServerPort
    print("socket tcp service connect to: ",ServerIp, ServerPort)
    #创建socket类的实例,并绑定和监听,闲置最大连接数为2.        
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind((ServerIp,int(ServerPort)))
    s.listen(2)
    print('server is listening,waiting for connection......')
     
    #创建一个新的进程来处理客户端的请求
    while True :
        sock,addr=s.accept()
        #注意accept方法得到的是一个socket类和一个端口地址的元组。用print命令很容易验证。
        print(sock,addr)
        try:
            t=threading.Thread(target=tcplink,args=(sock,addr))
            tname=t.name
            print('Now {:s} is running for connection from {:s}'.format(tname,addr[0]))
            t.start()
        except :
            print("Server is block")
            
 

def udp_client_run():
    global ServerIp
    global ServerPort
    print("udp socket client connect to: ",ServerIp, ServerPort)
    ip_port=(ServerIp,int(ServerPort))
    BUFSIZE=1024
    udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

    while True:
        msg=input('input msg>>: ').strip()
        if not msg:continue

        udp_server_client.sendto(msg.encode('utf-8'),ip_port)

        back_msg,addr=udp_server_client.recvfrom(BUFSIZE)
        print(back_msg.decode('utf-8'),addr)
    
    print("Connection is closed by client")
        
  
def udp_service_run():  
    global ServerIp
    global ServerPort
    print("udp socket service connect to: ",ServerIp, ServerPort)
    ip_port=(ServerIp,int(ServerPort))
    BUFSIZE=1024
    udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    udp_server_client.bind(ip_port)

    while True:
        msg,addr=udp_server_client.recvfrom(BUFSIZE)
        print(msg,addr)

        udp_server_client.sendto(msg.upper(),addr)
        
    print("Connection is closed by service")


if __name__ == '__main__':
    if len(sys.argv) == 3 :
        ServerIp=sys.argv[1] 
        ServerPort=sys.argv[2]

        serviceType=input('is client or service?: ').strip()
        protocolType=input('is tcp or udp?: ').strip()
        if protocolType=='tcp':
            if serviceType=='client':
                tcp_client_run()
            else:
                tcp_service_run()
                
        else:
            if serviceType=='client':
                udp_client_run()
            else:
                udp_service_run()
        
    else: 
        print("Use: python3 tcp_client.py 192.168.1.1 9999")
    
    
    
    

 

 

客户端和服务端都执行 python3 tcp_client.py 192.168.1.1 9999来测试,选择是客户端还是服务器,tcp还是udp

 

之后可以正常通信。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章