Python笔记(三)

2016/02/17 Python 阅读次数:

TCP/UDP

网络的目的:

信息的传递和数据的共享
地址是用来标记一台主机

IP地址:
作用 – 用来标识网络中的一台主机
构成 – 网络号 主机号
网络号 主机号
192.168.113 .116
IPv4 使用4个字节描述 21亿
IPv6 使用8个字节描述

ping:
能ping通网络一定是通的,ping不代表可能通也可能不通

分类
域名 www.baidu.com –域名解析DNS—> ip 111.13.101.208

ifconfig:
查看网卡中的IP
ping
域名或者IP 测试我与主机网络是否畅通
sudo ifconfig ens33 192.168.1.138
端口:

作用 – 用来标识主机中一个应用程序
IP + 端口的组合 确定网络中唯一的程序
端口用来标识主机中的一个用应用程序
端口的范围:0 - 65535
知名端口:
范围:0-1024(不包含1024)
80端口分配给HTTP服务
21端口分配给FTP服务
https 443
ssh 22
动态端口:
范围:1024-65535
socket:

socket 简称: 套接字
原意:插孔/插座的意思
本质:对底层网络协议TCP/IP的封装,并且提供了一套应用程序接口(API)

套接字使用:
socket() 创建
sendto() 发送数据

recvfrom() 接受数据

close() 关闭

bytes 类型和str类型的相互转化:

str —编码—>bytes
str.encode(“utf-8”)
bytes —解码—->str
bytes.decode(“utf-8”)

如果编码和解码的时候采用的编码方案是UTF-8,不用编码解码

对同一段数据而言,编码的时候有参数用 编码方案 和解码方案必须是同一个编码

在windows的调试助手:
ubuntu — str.encode() —>windows调试助手
bytes.decode(“gbk”)<—

UDP服务器:
bind的作用:告诉操作系统,我的应用要使用某个固定端口
UDP客户端:


import socket
def main():
    upd_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    upd_socket.bind(("", 10086))
    book = input()
    upd_socket.sendto(book.encode(),("192.168.113.85",8081))
    while True:
        data,adder = upd_socket.recvfrom(1024)
        if data:
            print("%s" % str(adder))
            print("%s" % data.decode())
        else:
            print("服务器已关闭")
            break
    upd_socket.close()
if __name__ == '__main__':
    main()

UDP服务端:


import socket
def main()
    upd_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    upd_socket.bind(("", 8080))
while True:
    data,adder = upd_socket.recvfrom(1024)
    print("%s" % str(adder))
    print("%s" % data.decode())
    nook = input()
    upd_socket.sendto(nook.encode(),("192.168.113.119", 10086))
if __name__ == '__main__':
    main()

UDP简单聊天案例:


import socket
def jieshou(udp_socket):
    data, remote_address = udp_socket.recvfrom(1024)
    print("收到来自%s的数据:%s" % (str(remote_address), data.decode()))
    udp_socket.sendto(data, remote_address)
def fasong(udp_socket):
    ip = input("IP地址:")
    prot = int(input("端口:"))
    book = input("输入内容")
    udp_socket.sendto(book.encode(),(ip, prot))
def print_menu():
    """菜单"""
    print("请选择功能:1.发送信息 2.接受信息 3.退出")
def main():
    """显示界面"""
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp_socket.bind(("",6666))
    while True:
        print_menu()
        num = input("请选择额:")
        if num == "1":
            fasong(udp_socket)
        elif num =="2":
            jieshou(udp_socket)
        elif num == "3":
            break
        else:
            print("输入错误哦")
    udp_socket.close()
if __name__ == '__main__':
    main()

UDP发送飞秋消息



import socket
def main()
    # 发送飞秋消息
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    i =116
    while True:
        str1 = input("请输入内容:")
        str2 = "1:324244:小道士:ubuntu:32:" + str1
        ip_num = "192.168.113." + str(i)
        udp_socket.sendto((str2).encode("gbk"),(ip_num,2425))
    udp_socket.close()
if __name__ == '__main__':
    main()

正向工程:– 表象和自己理解去实现

逆向工作:– 接近底层根据源代码写出自己的

TCP:

TCP是面向连接:
需要进行,创建socket连接、数据传送、关闭连接
在数据传输的时候,必须双方先建立连接,才能通信

TCP 数据传输:
具有应答机制,就是双方都必须有响应,方可传输数据
超时重传,如果发送超时,会进行下次重传,这样就避数据丢包现象
检错功能,能进行数据检错,对发送和接受数据进行效验
流量控制,避免出现阻塞现象,发送方太快,接受方太慢,就容易产生阻塞

TCP与UDP的不同点:
面向连接(确认有创建三方交握,连接已创建才作传输。)
有序数据传输
重发丢失的数据包
舍弃重复的数据包
无差错的数据传输
阻塞/流量控制

UDP 在传输数据时不需要连接,直接发送消息即可

TCP客户端:


import socket
def main():
    # 创建客户端套接字
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # connect填写远程服务器ip
    tcp_socket.connect(("192.168.113.146", 10050))
    while True:
        data = input("输入:")
        tcp_socket.send(data.encode("GBK"))
        recv_data = tcp_socket.recv(10)
        # tcp需要判断服务器是否关闭
        if recv_data:
            print("收到数据" + recv_data.decode("GBK"))
        else:
            print("对方关闭了链接")
            break
    tcp_socket.close()
if __name__ == '__main__':
    main()

TCP服务端:


import socket
def main():
    tcp_server =socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server.bind(("", 10050))
    # listen 变成被动套接字,只有被动套接字才能接受客服端消息
    # 128参数值 等待缓冲区,相当于容量,越大就接受越多,具体给多少,要看系统
    tcp_server.listen(128)
    # 返回值 客户socket---客户套接字
    # 客户端地址,标识客户端相关信息系
    clie_socket,addrs = tcp_server.accept()
    while True: # 在进行无无线循环的时候,必须放在客户套接字下面,接收上面
        # recv 是接收从客户端发过来的消息
        recv_data = clie_socket.recv(1024)
        if recv_data:
            clie_socket.send(recv_data)
            print(recv_data)
            # print(tcp_server)
            # print(clie_socket, addrs)
            # print(clie_socket)
            # print(addrs)
        else:
            clie_socket.close()
            print("客户端已关闭")
            break
    tcp_server.close()
if __name__ == '__main__':
    main()

TCP下载文件案例:
在写代码之前,先分析我们要实现那些功能,怎么实现
1、要写个客户端和一个服务端:
2、客户端需要 创建套接字,进行输入 ip,port,文件名
3、将输入的文件名发送给服务器
4、等待服务器返回我们消息
5、若是服务器有我们需要的文件,将结果返回给客户端,客户端写入新建的文件中
6、服务端:需要创建套接字,进行端口绑定
7、将主动套接字变为被动套接字
8、接受每个客户发送过来的消息
9、服务端接受到客户端发送来的文件名,在我当前目录查找是否存在;
10、若是存在该文件,读取该文件,发送给客户端。

文件下载客户端:


import os
import socket
def main():
    # 创建客户端socket
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接服务器 输入IP ,port ,文件名
    server_ip = input("ip地址:")
    server_port = int(input("端口:"))
    file_name = input("文件名:")
    # 连接服务器
    tcp_socket.connect((server_ip, server_port))
    # 下载的文件名
    tcp_socket.send(file_name.encode())
    # 接受文件,保存在本地
    file = open(file_name, "wb")
    count = 0
    while True:
        data = tcp_socket.recv(1024)
        if data:
            print("收到消息")
            file.write(data)
            count += len(data)
        else:
            file.close()
        if count == 0:
            os.remove(file_name)
            # os.remove(file_name)
            print("没有下载文件")
        else:
            print("文件传输完毕")
            break
    tcp_socket.close()
if __name__ == '__main__':
    main()

文件下载服务器:


import socket
def get_add(file_name):
    # 读取文件,判断是否存在
    print(file_name)
    try: # 读取的文件不存在会报错,需要加入判断
        file = open(file_name,"rb")
        # 将打开的文件全部读取给data
        data = file.read()
        print(data)
    except Exception as err: # 若是报错了不需要,关闭文件,因为没有打开
        print("你下载的文件不存在")
        # 若是没有报错,执行else
    else:
        # 关闭打开的文件/
        file.close()
        # 关闭了,文件需要返回一个结果,进行二次运算
        return data
        # 服务端程序在Pycham中不能让在二级目录中,不然会读取不到信息
def main():
    # 创建服务器套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置套接字选项 地址重用现象 套接字 选项 重用地址 1代表设置 0代表取消
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 绑定服务器端口
    tcp_server.bind(("",6664))
    # 变被动套接字 ,起到监听的功能
    tcp_server.listen(128)
    # 需要多次进行接收每个客户信息,需要无限循环
    while True:
        # 取出每个客户的套接字,进行每个客户端服务
        clie_socket, adder_ip = tcp_server.accept()
        # 收到的每个客户端消息
        file_name = clie_socket.recv(1024)
        print(file_name)
        # 判断客户端传过来的文件是否存在 通过封装函数,用reuten返回结果给data,
        data = get_add(file_name)
        # 判断返回的data是否为空,若是不为空,代表读取到信息,进行读取发送给客户端
    if data:
        # 需要用每个客户的socket进项发送消息,不能使用接收的scoket
        clie_socket.send(data)
    # 关闭客户socket
    clie_socket.close()
if __name__ == '__main__':
    main()

三次握手:

tcp_socket.connect() 发起三次握手,若是没有连接上,就会报错
服务器 会有个2个握手队列,一个正在进行握手队列,一个是以完成握手队列
listen(backlog) 表示指定完成握手队列长度(其他系统一般表示两个队列之和)
apccpet 取出一个队列,队列中就会删除一个
四次挥手:

FIN 完成 finish

主动断开的叫主动端: tcp规定 TIME_WAIT状态。防止ACK丢失,需要保持 30s-2分钟端口不能重新绑定

Search

    Table of Contents