基于python的socket通信


网络通信

前言

什么是TCP/IPUDP

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。

UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。

如下图,TCP和UDP写两者的关系图。

基于python的socket通信

 

Socket是什么

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

Socket在TCP和UDP协议的那块位置,如下图所示。

基于python的socket通信

 

基于TCP协议的网络通信

       基于TCP协议的网络通信,就类似于:一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。

基于python的socket通信

 

基于TCP协议的网络通信,就如上图所示。先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

程序设计:

服务器端:

服务器程序要先与客户机程序启动,步骤以及调用函数:

1)调用socket()函数创建一个流式套接字,返回套接字号s

2)调用bind()将s绑定到已知地址,通常为本地ip

3)调用listen()将s设为监听模式,准备接收来自各客户端的连接请求

4)调用accept()等待接受客户端连接请求

5)如果接收到客户端请求,则accept()返回,得到新的套接字ns

6)调用rev()接收来自客户端的数据,调用send()向客户端发送数据

7)与客户端通信结束,服务器端可以调用shutdown()对方不再接收和发送数据,也可以由客户端程序断开连接,断开连接后,服务器进程调用closesocket()关闭套接字ns,此后服务器返回第四步

8)如果要退出服务器程序,则调用closesocket()关闭最初的套接字s

客户端:

客户端程序步骤以及调用函数:

1)调用WSAStartup()函数加载Windows Sockets动态库,然后调用socket()函数创建一个流式套接字,返回套接字号s。

2)调用connect()函数将套接字s连接到服务器

3)调用send()函数向服务器发送数据,调用recv()函数接收来自服务器的数据。

4)与服务器的通信结束后,客户端程序可以调用close()函数关闭套接字。

基于UDP协议的网络通信

 如果Socket通信基于UDP,则数据传输前不需要连接,类似发短信或发电报,即使对方不在线,也可以发送数据,发送的数据在指定时间没有得到对方响应,则视为操作超时,可以选择超时后重新发送数据。

基于python的socket通信

Python设计中的相关函数:

socket()函数

socket()函数用于创建与指定的服务提供者绑定套接字,函数原型如下:socket=socket.socket(familly,type)

参数说明如下:familly,指定协议的地址家族,可为AF_INET或AF_UNIX。

AF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。

type,指定套接字的类型。

s=socket.socket() #  初始化一个TCP类型的Socket

s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #初始化一个UDP类型的socket

bind()函数由服务器端调用

bind()函数可以将本地地址与一个Socket绑定在一起,函数原型如下:socket.bind( address ),参数address是一个双元素元组,格式是(host,port)。host代表主机,port代表端口号。

listen()函数

listen()函数可以将套接字设置为监听接入连接的状态,函数原型如下:

listen(backlog);参数backlog指定等待连接队列的最大连接数。默认是1,一般设置为5

accept()函数

在服务器端调用listen()函数监听接入连接后,可以调用accept()函数来等待接受连接请求。accept()的函数原型如下:connection, address = socket.accept()

调用accept()方法后,socket会进入waiting状态。客户请求连接时,accept()方法会建立连接并返回服务器。accept()方法返回一个含有两个元素的元组(connection,address)。第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素 address是客户的Internet地址。

recv()函数  TCP接收数据

调用recv()函数可以从已连接的Socket中接收数据。recv()的函数原型如下:

buf = sock.recv(size)

参数sock是接收数据的socket对象,参数size指定接收数据的缓冲区的大小。recv()的函数的返回接收的数据。

send()函数   TCP发送数据

调用send()函数可以在已连接的Socket上发送数据。send()的函数原型如下:sock.recv(buf),参数sock是在已连接的Socket上发送数据。参数buf是也要已连接的Socket上发送数据。

close()函数

close ()函数用于关闭一个Socket,释放其所占用的所有资源。socket()的函数原型如下:s.closesocket();参数s表示要关闭的Socket。

Sendto(): 使用UDP发送数据使用

Recvfrom():UDP接收数据专用

sk.recvfrom(bufsize[.flag])

与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

 sk.sendto(string[,flag],address)

将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

 

基于TCP协议python的socket通信:

#服务器端
import socket
s=socket.socket() #
host=input("请输入IP:")
s.bind((host,8888))#
s.listen(5)
while True:
    c,add=s.accept()#等待连接,c表示新的套接字,add表示连接的ip地址
    while True:
        try:
            data = c.recv(1024)
            print(data.decode("utf-8"))
            str=input("请输入你要回复的消息")
            c.send(str.encode())
        except Exception:
            break
    c.close()
s.close()

#客户端
import socket
s=socket.socket() #
host=input("请输入IP:")
s.connect((host,8888))
while True:
    data = input('>>>请输入发送给服务器的消息').strip()
    s.send(data.encode('utf-8'))
    ret = s.recv(1024)
    print(ret.decode('utf-8'))

  

基于UDP协议的python程序设计

#服务器端
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #
s.bind(("127.0.0.1",8888))#
while True:
    while True:
        try:
            data,addr = s.recvfrom(1024)
            print(data.decode("utf-8"))
            str=input("请输入你要回复的消息")
            s.sendto(str.encode(),addr)
        except Exception:
            break
s.close()

#客户端
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #
s.connect(("127.0.0.1",8888))
while True:
    data = input('>>>请输入发送给服务器的消息').strip()
    s.sendto(data.encode('utf-8'),('127.0.0.1',8888))
    ret = s.recv(1024)
    print(ret.decode('utf-8'))

  基于socket的其它应用

ip地址查询

import socket
import time
import requests
from lxml import etree

def ym_ip(url):
    ip_list=[]
    rs=socket.getaddrinfo(url,None)
    for i in rs:
        ip_list.append(i[4][0])
    return ip_list
print(ym_ip("www.scitc.com.cn"))
print(ym_ip("www.baidu.com"))

CDN技术

#结合ip查询的函数  
#实现CDN判断
def  check_CDN(url):
    ip_list=ym_ip(url)
    if len(ip_list)>1:
        return "存在CDN"
    else:
        return "不存在CDN"
print(check_CDN("www.scitc.com.cn"))
print(check_CDN("www.baidu.com"))

子域名获取

def check_zym(url): # url www.scitc.com.cn
    url=url.replace("www",'')  # url  .scitc.com.cn
    f =open('dic.txt',encoding="utf-8")
    for i in f:
        i=i.replace('/n','')
        url_new=i+url
        #print(url_new)
        #socket.gethostbyname(url)方法中的url参数不能带有
        #“http”这样的协议前缀,否则不能解析成IP地址。
        try:
            ip=socket.gethostbyname(url_new)
            print(url_new,"--->",ip)
            time.sleep(0.1)
        except Exception:
            time.sleep(0.1)
            pass
check_zym('www.cbyzsc.com')

 

原创文章,作者:1402239773,如若转载,请注明出处:https://blog.ytso.com/276468.html

(0)
上一篇 2022年7月23日
下一篇 2022年7月23日

相关推荐

发表回复

登录后才能评论