网络编程--套接字(TCP/UDP/socket/HTTP)

socket套接字编程

  1. 套接字:实现网络编程进行数据传输的一种技术手段

  2. python实现套接字编程

      import  socket
    
  3. 套接字类型

    流式套接字(SOCK_STREAM):以字节流的方式进行数据传输,实现TCP网络传输方案。

    数据报套接字(SOCK_DGRAM): 以数据报形式传输数据,实现UDP网络传输方案。

    面向连接-tcp协议-可靠地-流式套接字
    面向无连接-udp协议-不可靠-数据报套接字

TCP套接字编程

  • 服务端流程
  1. 创建套接字对象

    sockfd = socket.socket(socket_family=AF_INET,
    		 socket_type = SOCK_STREAM,
    		 proto = 0)
    

    功能: 创建套接字对象
    参数:

     socket_family 网络地址类型			
     AF_INET==>IPv4
     socket_type 套接字类型
     SOCK_STREAM  流式
     SOCK_DGRAM  数据报
     proto  子协议选择,通常为0
     返回值: 套接字对象
    
  2. 绑定地址

    sockfd.bind(addr)
    	功能: 绑定本机网络地址
    	参数: 元组,(ip,port)   ('0.0.0.0',8888)
    
  3. 设置监听

    sockfd.listen(n)
    	功能:将套接字设置为监听套接字,创建监听队列
    	参数:监听队列大小
    
  4. 等待处理客户端请求

    connfd,addr = sockfd.accept()
    	功能:阻塞等待处理客户端请求
    	返回值:connfd  客户端连接套接字
    		   addr   连接的客户端地址
    

    阻塞函数:

    程序运行过程中遇到阻塞函数则暂停执行,直到达到某种条件后继续运行。

  5. 收发消息

    data = connfd.recv(buffersize)
    	功能: 接收客户端消息
    	参数:每次最多接收消息的大小
    	返回值:收到的消息内容
    
    n = connfd.send(data)
    	功能:发送消息
    	参数:要发送的内容  bytes格式
    	返回值:发送了多少字节
    
    	* str --> bytes  string.encode()
    	* bytes --> str  bytes.decode()
    
  6. 关闭套接字

    sockfd.close()
    	功能: 关闭套接字
    
  • 服务端代码块实例:

    # tcp_server.py
    
    import socket 
    
    # TCP创建套接字
    sockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    # 绑定地址
    sockfd.bind(('0.0.0.0',8888))
    
    # 设置监听
    sockfd.listen(3)
    
    # 等待客户端连接
    print("Waiting for connect ....")
    connfd,addr = sockfd.accept()
    print("Connect from",addr) # 客户端地址
    
    # 消息收发
    data = connfd.recv(1024)
    print("Receive message:",data.decode())
    
    n = connfd.send(b"Receive your message")
    print("Send %d bytes"%n)
    
    # 关套接字
    connfd.close()
    sockfd.close()
    
  • 客户端流程

  1. 创建套接字
    *只有相同类型套接字才可以通信

  2. 请求连接

    sockfd.connect(addr)
    	功能: 连接服务端
    	参数: 元组, 服务端地址
    
  3. 消息收发
    *消息的收发要配合

  4. 关闭套接字

  • 客户端代码块实例:

    # tcp_client.py
    from socket import * 
    
    # 创建套接字
    sockfd = socket()
    
    # 发起连接
    server_addr = ('127.0.0.1',8888)
    sockfd.connect(server_addr)
    
    # 收发消息
    data = input(">>")
    sockfd.send(data.encode()) # 转换为字节串
    data = sockfd.recv(1024)
    print("From server:",data.decode())
    
    #关闭套接字
    sockfd.close()
    
  • 一、TCP套接字传输特点
    1.tcp连接中当一端退出,另一端如果阻塞在recv,则recv会立即返回一个空子串
    2.tcp连接中如果另一端已经不存在,在试图使用send向其发送内容时会出现BrokenPipe(通道破坏)

  • 二、网络收发缓冲区
    1.缓冲区有效的协调了消息的收发速度
    2.send,recv,实际是向缓冲区发送接收消息,当缓冲区不为空的时候,reccv就不会阻塞

  • 三、粘包问题
    原因:tcp以字节流方式传输数据,没有消息边界,多次发送的内容如果被一次接收就会形成粘包

    影响:如果每次发送的内容是需要独立解析的含义,此时粘包会对消息解析产生影响

    处理
    1.人为的添加消息便捷,
    2.控制发送速

UDP套接字编程

  • 服务端流程
  1. 创建套接字

    sockfd = socket(AF_INET,SOCK_DGRAM)
    
  2. 绑定地址

     sockfd.bind(addr)
    
  3. 收发消息

     data,addr = sockfd.recvfrom(buffersize)
     	功能:接收UDP消息
     	参数:每次最多接收多少字节内容
     	返回值:data接收到的消息
     			addr消息发送方地址
     n = sockfd.sendto(data,addr)
     	功能:发送UDP消息
     	参数: data发送的内容  bytes格式
     			addr目标地址
    
  4. 关闭套接字

  • 服务端代码:

    # udp_server.py
    
    from socket import *
    # 创建套接字
    sockfd = socket(AF_INET,SOCK_DGRAM)
    
    # 绑定地址
    server_addr = ("0.0.0.0",8888)
    sockfd.bind(server_addr)
    
    # 收发消息
    while True:
        data,addr = sockfd.recvfrom(1024)
        print("收到来自%s的消息:%s"%(addr,data.decode()))
        sockfd.sendto(b"shoudao",addr)
    
    # 关闭套接字
    sockfd.close()
    
  • 客户端流程

  1. 创建UDP套接字

     	sockfd = socket(AF_INET,SOCK_SGRAM)
    
  2. 发送接收消息

  3. 关闭套接字

  • UDP套接字客户端代码

    # udp_client.py
    
    from socket import *
    # 服务端地址
    HOST = "127.0.0.1"
    PORT = 8888
    ADDR = (HOST,PORT)
    
    # 创建套接字
    sockfd = socket(AF_INET,SOCK_DGRAM)
    
    # 收发消息
    while True:
        data = input("==>:")
        if not data:
            break
        sockfd.sendto(data.encode(),ADDR)
        msg,addr = sockfd.recvfrom(1024)
        print("来自:",msg.decode())
    
    sockfd.close()
    

  • 总结
    tcp套接字和udp套接字编程区别

      1.流式套接字以字节流方式传输数据,数据报套接字以数据报形式传输
      
      2.tcp套接字会有粘包问题,udp套接字由消息边界不会粘包
      
      3.tcp套接字保证消息的完整性,udp不保障
      
      4.tcp套接字依赖listen accept完成连接才能进行数据收发,udp套接字不需要
      
      5.tcp使用send recv 收发消息,udp使用sendto recvfrom
    
  • socket模块方法和socket套接字属性

    1. 部分socket模块方法

       socket.gethostname()			#显示主机名称
       soccket.gethostbyname("www.baidu.com")		#根据主机名获取IP地址。
       socket.getservbyname("mysql")		#根据服务获取监听端口		
       soclet.getservbyport(3306)			#根据端口获取服务名称
       socket.inet_aton("192.168.1.2")		#将IP地址转换为字节串
       socket.inet_ntoa(b'\xc0\xa8\x01\x01')	#将字节串转换为IP地址
      
    2. 套接字属性

      1. socket.family 地址类型

      2. socket.type 套接字类型

      3. socket.getsockname() 绑定地址

      4. socket.fileno() 获取文件描述符

         文件描述符:系统中么一个IO操作都会分配一个整数作为编号,该整数即这个IO文件描述符
         
         特点:每个IO的文件描述符不会重复
        
      5. getpeername() 获取套接字绑定地址

      6. setsockopt(leve1,option,value)

         功能:设置套接字选项
         
         参数:level选项类别	SOL_SOCKET
         	  option	具体选项内容
              value		选项值
        
  • UDP套接字广播
    广播定义:一端发送,多端接收
    广播地址:每个网段内的最大地址,向该地址发送,则网段内所有的主机都能接收

    from socket import *
    from time import sleep
    dest = ("0.0.0.0",5555)
    s = socket(AF_INET,SOCK_DGRAM)
    
    # 设置可以发送接受广播
    s.setsockopt(SOL_SOCKET,SO_BROADCAST,True)
    data = '''
    **********************
        4.4 清明前
        春风十里不如你
        000;
    **********************
    '''
    
    while True:
        sleep(2)
        s.sendto(data.encode(),dest)
    
    # broadcast_recv.py
    from socket import *
    # 创建套接字
    s = socket(AF_INET,SOCK_DGRAM)
    
    s.setsockopt(SOL_SOCKET,SO_BROADCAST,True)
    
    s.bind(("127.0.0.1",5555))
    
    while True:
        msg, addr = s.recvfrom(1024)
        print(msg.decode())
    
    

  • 利用TCP完成文件的传输
######服务端###############

from socket import * 

s = socket()
s.bind(('127.0.0.1',8888))
s.listen(3)

c,addr = s.accept()
print("Connect from",addr)

f = open('p.jpeg','wb')

while True:
    data = c.recv(1024)
    if not data:
        break 
    f.write(data)

f.close()
c.close()
s.close()
#########发送端#############
from socket import *

s = socket()
s.connect(('127.0.0.1',8888))

#自己设定的图片
f = open('timg.jpeg','rb')

while True:
    data = f.read(1024)
    if not data:
        break 
    s.send(data)

f.close()
s.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值