python 关闭udp端口_Python学习笔记(进)-网络编程(服务器、客户端.......)

1.端口

2**16 = 65536个 [0,65535)

12ac7f0aca2f8906860340c7a2c41bec.png

动态端口 1024-65535

查看端口 netstat - an

2.ip地址

ip地址包括两部分:网络地址和主机地址

ipv4

c4e406f34769a62dac012554ecb9f8c4.png

如果是C类 0 和255 不肯用(最大和最小)

0表示 网络号 例如:192.168.119.0四

255表示 广播地址192.168.119.255

2^10→K 2^20→M 2^30→G ipv4 2^32→4G

91d3097512ad40431494e05a98c4c489.png

3.socket SSS重要

进程间的通信 socket 套接字(插口)

tcp通信:慢 稳定 打电话 传输控制协议

udp通信:快 不稳定(丢数据)写信 用户数据包协议

f1ec1f5ea9662a2f59b11d80436df51d.png
from socket import *


s = socket(AF_INET,SOCK_DGRAM)
s.sendto("内容",("ip",8080))

ec8a880b3049c8157407dd18bea1bd47.png

---------------接收数据↓---

from socket import *

#创建套接字
s = socket(AF_INET,SOCK_DGRAM)
# 绑定本地的相关信息,如果不绑定,系统会随机分配
s.bind(("",7788))

s.sendto(b"haha",("ip",8080))
# 等待接收对方发送的数据
recvData = s.recvfrom(1024)  # 1024表示本次接收最大字节

print(recvData)
# 关闭套接字
s.close()

单工 半双工 全双工

python3 环境编写

f31853d9585723309d12bb51e05213b4.png
发送数据 代码↓
from socket import *

udpSocket = socket(AF_INET, SOCK_DGRAM)

destIp = input("请输入目的ip:")
destPort = int(input("请输入目的port:"))
sendData = input("请输入要发送的数据:")

#udpSocket.sendto(sendData.encode("utf-8"), (destIp, destPort))
udpSocket.sendto(sendData.encode("gb2312"), (destIp, destPort))

接收数据

from socket import *

udpSocket = socket(AF_INET, SOCK_DGRAM)
udpSocket.bind(("", 7789))
recvData = udpSocket.recvfrom(1024)
content, destInfo = recvData

print("content is %s"%content)
print("content is %s"%content.decode("gb2312"))

4.网络通信过程

a3086da036b5c09a54290cc654ac5337.png

75de715ef90d1939634e0fc25c6c2256.png

761dedfcb63cf0b1b95ea0f035ea8ee4.png

3db077f6b5026d869ae59f027bd30adb.png

5.聊天室的创建

6.模拟QQ聊天

from threading import Thread
from socket import *


# 接收数据
def recvData():
    while True:
        recvInfo = udp_s.recvfrom(1024)
        print("r>>%s:%s" % (recvInfo[1],recvInfo[0].decode("gb2312")))


# 发送数据
def sendData():
    while True:
        sendInfo = input("r<<")
        udp_s.sendto(sendInfo.encode("gb2312"),(destIp,destPort))


udp_s = None
destIp = ""
destPort = 0


def main():
    global udp_s
    global destIp
    global destPort

    destIp = input("请输入ip:")
    destPort = int(input("请输入端口:"))

    udp_s = socket(AF_INET,SOCK_DGRAM)
    udp_s.bind(("",8888))

    tr = Thread(target=recvData)
    ts = Thread(target=sendData)

    tr.start()
    ts.start()

    tr.join()
    ts.join()


if __name__ == '__main__':
    main()

01f3c46d2df11916cdc4509898bb283f.png

7.wireshark和tftp安装

tftp是服务器

df734efe85275f9fe23aa789c69c4c18.png

8.tftp服务器 自己编写客户端 下载服务器中的文件(未完待续)

e6ae40f0c785ca43ac7ad732e693cf07.png

66d8c8526fc73c40a38a7acf0753bb5c.png

10f5d75e2cd4d4fa92c25d7fc5e6aa6e.png

8.udp广播

单播 多播 广播

广播:

from socket import *

dest = ("<broadcast>",7788)
s = socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
s.sendto(b"haha",dest)

9.总结

UDP(用户数据包协议):

fec6fbef4ac9f19bde2ba531d13002cf.png

TCP(传输控制协议):

d60d33d9a4042ac5319d016520674c28.png

socket的套接字 是主动套接字

listen()将主动套接字变为被动

TCP服务器编写:

from socket import *

s = socket(AF_INET,SOCK_STREAM)
s.bind(('',7788))
s.listen(5)
# newSocket表示新的套接字(为这个客户端服务,s就可以等待其他客户端连接)
# sInfo表示新套接字的ip及port
newSocket,sInfo = s.accept()
recvData = newSocket.recv(1024)
print("%s:%s" % (str(sInfo),recvData.decode("gb2312")))
newSocket.close()
s.close()

服务器:

from socket import *
from multiprocessing import Process


def dealDatas():
    while True:
        recvData = newSocket.recv(1024)
        print("r>>%s" % recvData.decode("utf-8"))
        sendInfo = input("<<")
        if len(sendInfo)>0:
            sendData = newSocket.send(sendInfo.encode("utf-8"))
        else:
            break


s = socket(AF_INET,SOCK_STREAM)
s.bind(('',7788))
s.listen(5)

while True:
    newSocket,sInfo = s.accept()
    p = Process(target=dealDatas)
    p.start()
    newSocket.close()
    s.close()

客户端:

from socket import *

s = socket(AF_INET,SOCK_STREAM)

s.connect(("192.168.58.1",7788))

while True:
    sInfo = input("r>>")
    if len(sInfo) > 0:
        s.send(sInfo.encode("utf-8"))
    else:
        break
    recvData = s.recv(1024)
    print("%s" % recvData)

s.close()

10.Cisco Packet Tracer

213668ed41f6b8502d8b3f62425d093b.png

OSI 七层模型

03fdcf4d06114acd55f0d466aa12b9ef.png

ping命令 icmp协议 之后通过ARP协议获取MAC地址

ARP 根据IP 找MAC地址 RARP根据MAC地址找IP

链路层 接收MAC地址 1.广播MAC地址 2.电脑网卡物理IP地址

三台路由器连接连个不同网段的网络时

787ebdf04da9ece1bc40004e288cf026.png

ip地址标记逻辑地址

mac地址标记实际地址

netmask 掩码和ip地址一起确认网络号 (通过按位与)

默认网关:发送的ip不在同一个网段内,会把这个ip转发给默认网关

两个设备之间的通信 写的是mac地址 IP地址不变

面试题!!!!

访问百度时过程:若果是第一次的话,先确认网关,有网关确认网关MAC地址(APR),域名访问三次握手,客户端给服务器发送请求数据,之后对方将数据传输。

第一步:如果以域名访问,先解析出 http://baidu.com的ip地址

(1) ARP获取默认网关MAC地址

(2)之后组织数据发送给默认网关(ip是DNS服务器ip,MAC地址是默认网关的MAC地址)

(3)默认网关拥有转发数据的能力,把数据转发给路由器

(4)路由器根据自己的路由协议,来选择一个合适的较快的路径 转发数据给目的网关

(5)目的网关(DNS服务器所在地网关),把数据转发给DNS服务器

(6)DNS服务器查询解析出http://baidu.com对应IP地址,并把他原路返回给请求域名的client

第二步:

(1)得到http://baidu.com 对应的IP地址,发送tcp三次握手,进行连接

(2)使用http协议发送请求给web

(3)web服务器收到数据请求后,查询得到结果,原路返回给浏览器

(4)浏览器接收数据 通过自己的渲染功能显示网页

(5)浏览器关闭tcp连接 即第四次挥手,

DHCP 自动分配ip地址协议

11.TCP与UDP对比

5cdd05c85c65ace977a077aeab555eca.png

0e0243e3ea803f6f5b4db889ec9f3ab2.png

seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。

(面试题)为什么是三次握手 而不是两次!

主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

11.

18c8f8eedce3213c36b702db9ae05ea5.png

12.常见的网络攻击

DOS攻击

DNS攻击

ARP攻击

python 使用原始套接字

13.NAT网络地址转换器

53e739e205cc2e9ac9e9d5757a688ecd.png

14.多进程服务器 和多线程服务器

多进程服务器 需要在try下面关闭 新客户端套接字,多线程不关闭(因为线程共用)

多进程:

from socket import *
from multiprocessing import Process


def dealWithClient(newSocket,newAdress):
    while True:
        recvData = newSocket.recv(1024)
        if len(recvData)>0:
            print("%s:%s" % (str(newAdress),recvData))
        else:
            print("%s已关闭" % newAdress)
            break
    newSocket.close


def main():
    s = socket(AF_INET,SOCK_STREAM)
    s.bind(("",7788))
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.listen(5)
    try:
        while True:
            newSocket,newAdress = s.accept()
            p1 = Process(target=dealWithClient,args={newSocket,newAdress})
            p1.start()
            newSocket.close()
    finally:
        s.close()

if __name__ == '__main__':
    main()

多线程:

from socket import *
from threading import Thread


def dealWithData(newSocket,newAdress):
    while True:
        recvData = newSocket.recv(1024)
        if len(recvData)>0:
            print("%s:%s" % (str(newAdress),recvData))
        else:
            print("%s 断开" % newAdress)
            break
    newSocket.close


def main():
    s = socket(AF_INET, SOCK_STREAM)
    s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    s.bind(("", 5555))
    s.listen(5)
    try:
        while True:
            newSocket, newAdress = s.accept()
            t1 = Thread(target=dealWithData, args=(newSocket, newAdress))
            t1.start()
    finally:
        s.close()

if __name__ == '__main__':
    main()

单进程非阻塞服务器: !!!!!思想重要

from socket import *


s = socket(AF_INET,SOCK_STREAM)
s.setblocking(False)
s.bind(("",7788))
s.listen(10)
clientList = []
while True:
    try:
        newSocket,clientAdress = s.accept()
    except:
        pass
    else:
        print("新的客户端到来:%s" % str(clientAdress))
        newSocket.setblocking(False)
        clientList.append((newSocket,clientAdress))

    for clientsocket,clientAdr in clientList:
        try:
            recvData = clientsocket.recv(1024)
        except:
            pass
        else:
            if len(recvData) > 0:
                print("%s:%s" % (str(clientAdr),recvData))
            else:
                clientsocket.close()
                clientList.remove((clientsocket,clientAdr))
                print("%s已退出" % str(clientAdr))

select版服务器:(上限1024) → 轮询

poll:无上限 (与select相同)→ 轮询(慢)

epoll:无上限 → 事件通知机制

cf6eaf25383e43789db7be9384d06f99.png

select版服务器

from socket import *
import select


server = socket(AF_INET,SOCK_STREAM)
server.bind(("",8888))
server.listen(5)
socketlist = [server]

while True:
    readable,writeable,excptional = select.select(socketlist,[],[])

    for socket in readable:
        if socket == server:
            clientSocket,clientAddress = socket.accept()
            socketlist.append(clientSocket)
        else:
            recvData = socket.recv(1024)
            if recvData:
                socket.send(recvData)
                print("%s:%s" % (str(clientAddress),recvData))
            else:
                socketlist.remove(socket)
                socket.close()

epoll版服务器:

from socket import *
import select


s = socket(AF_INET,SOCK_STREAM)
s.bind(("",7777))
s.listen(5)
epoll = select.epoll()
epoll.register(s.fileno(),select.EPOLLIN|select.EPOLLET)

connections = {}
addresses = {}
while True:
    epoll_list = epoll.poll()
    for fd,event in epoll_list:
        if fd == s.fileno():
            client,addr = s.accept()
            connections[client.fileno()] = client
            addresses[client.fileno()] = addr
            # select.EPOLLIN判断事件是否接收数据的事件
            epoll.register(s.fileno(),select.EPOLLIN|select.EPOLLET)

        elif fd == select.EPOLLIN:
            recvData = connections[fd].recv(1024)
            try:
                if recvData:
                    print("%s:%s" % (str(addresses[fd]),recvData))
            except:
                pass
            else:
                epoll.unregister(fd)
                connections[fd].close()

计算密集型 (例如or嵌套for很多) → 占用大量CPU → 多进程

IO密集型 →需要网络工能,大量时间都在等待网络数据到来 → 多线程 协程

协程的 实现方法:生成器(yeild)

协程 greenlet版(安装greenlet) 还有一种方法yelid +next

from greenlet import greenlet
import time

def test1():
    while True:
        print("a")
        g2.switch()
        time.sleep(0.5)


def test2()
    while True:
        print("b")
        g1.switch()
        time.sleep(0.5)

gr1 = greenlet(test1)
gr2 = greenlet(test2)

g1.switch

协程方法3 gevent (安装)

当gevent 遇到耗时操作时 切换执行 → gevent.sleep(1)

如果不耗时则往下执行

import gevent


def f(n):
    for i in range(n)
        print(gevent.getcurrent(),i)
        gevent

g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevert.spawn(f,5)

g1.join()
g2.join()
g3.join()

gevent版服务器

import gevent
from gevent import socket,monkey
monkey.patch_all()


def dealData(client,addr):
    while True:
        try:
            recvData = client.recv(1024)
        except:
            pass
        else:
            if recvData:
                print("%s:%s" %(str(addr),recvData))
            else:
                client.close()


s = socket.socket()
s.bind(("",6666))
s.listen(5)
while True:
    cilent,addr = s.accept()
    gevent.spawn(dealData,cilent,addr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值