victory的博客

长安一片月,万户捣衣声

0%

几种web服务器的比较

select版服务器

优点:跨平台
缺点:
单个进程能够监视的文件描述符的数量存在最大限制(1024)
轮询检测,效率较低

poll版服务器

优点:解决了套接字有上限的问题
缺点:轮询检测

epoll版服务器

优点:
没有1024的最大限制
事件通知机制,效率较高

金刚川-Sacrifice

2020.10.27 周二
看到师兄在WeChat群里说最近有部电影-金刚川特别好,所以今天和我的小可爱在万达广场的万达影院看了这部电影。
1953年,抗美援朝战争进入最终阶段,志愿军在那金城发动最后一场战役。然而要到达金城就要跨过眼前的这条江,志愿军物资装备匮乏,面对美军战斗机不断的对桥进行轰炸,他们唯一能做出回应的仅有两门高炮和为数不多的炮弹…一遍又一遍的轰炸,一遍又一遍的修桥…最终志愿军们搭了一个人桥跨过了眼前这条江。在影片中印象最深刻的是由张译饰演的张飞张排长;在一次与敌机的战斗中被打掉了一条胳膊,一条腿…他把三枚炮弹挂在脖子上,用木棍支撑着身体艰难的爬到高炮上准备迎接下轮的战斗;敌机来了,他用一只手,一只脚操作着原本三五个人完成发射的高炮,面对敌机的轰炸无所畏惧,最终击落敌机。最后说说可爱的中国人民志愿军,面对死亡他们无所畏惧,每一个人都不怕死,为了国家,为了人民,随时准牺牲;
电影一开始的时候,在幕布上看到金刚川-sacrifice,我很疑惑,为什么翻译为sacrifice,但看完整个影片,我找到了答案,为了过江,为了保卫祖国安全,让中国人民过上安宁的日子,他们时刻准备好了牺牲,准备好了面对死亡。
Sacrifice

使用tcp协议进行通信过程中的三次握手和四次挥手

TCP在真正的读写操作之前,server与client之间必须建立一个连接。
当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接。
连接的建立通过三次握手释放则需要四次挥手
tcp三次握手和四次挥手

tcp稳定而udp不稳定的原因

在tcp中,如果有一方收到了对方的数据,一定会发送ack确认包给发送方,而在udp中,没有这个过程,因此导致了tcp稳定,而udp不稳定。

从浏览器访问百度的整个访问过程

实际场景

在浏览器的地址输入栏,输入www.baidu.com访问百度。

访问过程

  1. 1.先要解析出baidu.com对应的ip地址
    1. 1.先要知道默认网关的MAC地址
      1. 1.使用ARP获取默认网关的MAC地址
    2. 2.组织数据发送给默认网关(IP还是DNS服务器的IP,但MAC地址是默认网关的MAC地址)
    3. 3.默认网关拥有转发数据的能力,把数据转发给路由器
    4. 4.路由器根据自己的路由协议来选择一个合适的较快的路径转发数据给目的网关
    5. 5.目的网关(DNS服务器所在的网关),把数据转发给DNS服务器
    6. 6.DNS服务器查询解析出baidu.com对应的IP地址,并把它原路返回给请求这个域名的客户端
  2. 2.得到了baidu.com对应的IP地址后会发送TCP的3次握手,进行连接
  3. 3.使用HTTP协议发送请求数据给WEB服务器
  4. 4.WEB服务器收到请求数据之后,通过查询自己的服务器得到响应的结果,原路返回个浏览器
  5. 5.浏览器接收到数据后,通过浏览器自己的渲染功能来显示这个网页
  6. 6.浏览器关闭TCP连接,即4次挥手

几种常见tcp、ip协议以及常见术语

ICMP(internet 控制报文协议)—>使用ping命令时

ARP(地址解析协议)—>根据IP地址找MAC地址

RARP(反向地址解析协议)—>根据MAC地址找IP地址

MAC(媒体访问控制地址)—>网卡的编号

IP:标记逻辑上的地址

mac:标记实际转发数据时的设备地址

DHCP(动态主机配置协议):发现当前局域网内没有IP的电脑,给这台电脑自动分配IP

netmask:和ip地址一起来确定网络号

默认网关:发送的ip不在同一个网段内,那么会把这个数据转发给默认网关
Note:
MAC地址在两个设备之间通信时在变化
IP地址在整个通信过程中都不会发生变化

tcp的客户端/服务器端代码编写

tcp服务器端代码编写

#coding=utf-8
from socket import *

# 创建socket
tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息
address = ('', 7788)
tcpSerSocket.bind(address)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcpSerSocket.listen(5)

# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器
# newSocket用来为这个客户端服务
# tcpSerSocket就可以省下来专门等待其他新客户端的链接
newSocket, clientAddr = tcpSerSocket.accept()

# 接收对方发送过来的数据,最大接收1024个字节
recvData = newSocket.recv(1024)
print('接收到的数据为:%s'%recvData)

# 发送一些数据到客户端
newSocket.send("thank you !")

# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
newSocket.close()

# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcpSerSocket.close()
阅读全文 »

使用tftp协议从服务器下载文件到客户端

Code

import struct
from socket import *
import time
import os

def main():


    #0. 获取要下载的文件名字:
    downloadFileName = raw_input("请输入要下载的文件名:")    

    #1.创建socket
    udpSocket = socket(AF_INET, SOCK_DGRAM)

    requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)

    #2. 发送下载文件的请求
    udpSocket.sendto(requestFileData, ("192.168.119.215", 69))

    flag = True #表示能够下载数据,即不擅长,如果是false那么就删除
    num = 0
    f = open(downloadFileName, "w")

    while True:
        #3. 接收服务发送回来的应答数据
        responseData = udpSocket.recvfrom(1024)

        # print(responseData)
        recvData, serverInfo = responseData

        opNum = struct.unpack("!H", recvData[:2])

        packetNum = struct.unpack("!H", recvData[2:4])

        print(packetNum[0])

        # print("opNum=%d"%opNum)
        # print(opNum)

        # if 如果服务器发送过来的是文件的内容的话:
        if opNum[0] == 3: #因为opNum此时是一个元组(3,),所以需要使用下标来提取某个数据
            

            #计算出这次应该接收到的文件的序号值,应该是上一次接收到的值的基础上+1
            num = num + 1

            # 如果一个下载的文件特别大,即接收到的数据包编号超过了2个字节的大小
            # 那么会从0继续开始,所以这里需要判断,如果超过了65535 那么就改为0
            if num==65536:
                num = 0

            # 判断这次接收到的数据的包编号是否是 上一次的包编号的下一个
            # 如果是才会写入到文件中,否则不能写入(因为会重复)
            if num == packetNum[0]:
                # 把收到的数据写入到文件中
                f.write(recvData[4:])
                num = packetNum[0]

            #整理ACK的数据包
            ackData = struct.pack("!HH", 4, packetNum[0])
            udpSocket.sendto(ackData, serverInfo)

        elif opNum[0] == 5:
            print("sorry,没有这个文件....")
            flag = False

        # time.sleep(0.1)

        if len(recvData)<516:
            break

    if flag == True:
        f.close()
    else:
        os.unlink(downloadFileName)#如果没有要下载的文件,那么就需要把刚刚创建的文件进行删除

if __name__ == '__main__':
    main()

在linux环境下使用 udp+多线程 模拟QQ

分析

程序主要的两个功能

  • 发送数据(Send Data)
  • 接收数据(Reveive Data)

使用多线程的原因
不使用多线程的情况下,在程序暂停等待发送方输入发送内容时,若发送方不输入内容,则程序一直卡在这里;此时另外一放发送数据由于程序暂时等待输入内容也不能打印消息。
使用了多线程,接收数据、发送数据的程序分别由一个线程来处理,且两个线程互不影响,发送方不输入内容时,另一方发送消息发送方就能接收到。
Note:通信的两台计算机必须在同一个局域网!!!

阅读全文 »