Python系列8之socket

目录

  socket  

  简单的聊天机器人

  简单的ftp上传

  粘包问题的解决

一. socket模块

  socket,俗称套接字,其实就是一个ip地址和端口的组合。类似于这样的形式(ip,  port),其中ip代表的是某个主机,port代表的是某个应用,我们可以通过socket和另外的一台主机进行通信。

  关于socket源码的解析在tarnado系列文章中,正在写中。。。。。

  1. 通信的方式

    tcp通信

    udp通信

    基于unix的通信

   2. socket的方法 

# 暂时知道的也就这么多,之后要是在用到其他的我会继续进行保存
    Methods of socket objects (keyword arguments not allowed):
    
    _accept() -- accept connection, returning new socket fd and client address
    bind(addr) -- bind the socket to a local address 给本地地址绑定一个socket套接字
    close() -- close the socket 关闭一个套接字
    connect(addr) -- connect the socket to a remote address     连接到远端主机
    connect_ex(addr) -- connect, return an error code instead of an exception
    dup() -- return a new socket fd duplicated from fileno()
    fileno() -- return underlying file descriptor
    getpeername() -- return remote address [*]
    getsockname() -- return local address
    getsockopt(level, optname[, buflen]) -- get socket options
    gettimeout() -- return timeout or None
    listen([n]) -- start listening for incoming connections
    recv(buflen[, flags]) -- receive data   接受数据
    recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)    接受数据到缓冲区中,
    recvfrom(buflen[, flags]) -- receive data and sender's address
    recvfrom_into(buffer[, nbytes, [, flags])
      -- receive data and sender's address (into a buffer)
    sendall(data[, flags]) -- send all data 发送数据给远端主机,3.x之后只能发送字节形式,因此在发送的时候一般要进行转换bytes
    send(data[, flags]) -- send data, may not send all of it 也是发送数据,区别在于send发送的不完整,随机进行发送的,二sendall发送的完整
    sendto(data[, flags], addr) -- send data to a given address 基于udp发送数据的
    setblocking(0 | 1) -- set or clear the blocking I/O flag    是否设置成阻塞模式0 代表阻塞,1代表非阻塞
    setsockopt(level, optname, value) -- set socket options     设置一些socket的桉树
    settimeout(None | float) -- set or clear the timeout    设置超时市场
    shutdown(how) -- shut down traffic in one or both directions    
    if_nameindex() -- return all network interface indices and names
    if_nametoindex(name) -- return the corresponding interface index
    if_indextoname(index) -- return the corresponding interface name
 
     [*] not available on all platforms!

二. 简单的聊天机器人

  如果发送一个数据,服务器就会给他回复一个数据 + 你好

 1 # -*- coding:utf-8 -*-
 2 # zhou
 3 # 2017/7/3
 4 
 5 import socket
 6 # 创建一个server对象
 7 server_obj = socket.socket()
 8 # 绑定一下端口
 9 server_obj.bind(("127.0.0.1", 8888, ))
10 # 设置监听的等待队列长度为5,当大于5的时候就拒绝连接
11 server_obj.listen(5)
12 
13 while True:
14     # 等待接受客户端的连接,为阻塞方式
15     conn, address = server_obj.accept()
16     # 发送欢迎信息
17     conn.sendall(bytes("欢迎来到简单的聊天室..", encoding='utf-8'))
18     while True:
19         # 接受到对面的消息就会把对面消息后面加上你好重新发送回去
20         ret = str(conn.recv(1024), encoding='utf-8')
21         if ret == 'q':
22             # 如果对面发送的为q就退出
23             break
24         conn.sendall(bytes(ret + ",你好", encoding='utf-8'))
server
# -*- coding:utf-8 -*-
# zhou
# 2017/7/3

import socket

client = socket.socket()
client.connect(("127.0.0.1", 8888, ))
# 接受欢迎信息并打印
ret = str(client.recv(1024), encoding='utf-8')
print(ret)

while True:
    message = input("请输入您要发送的内容:")
    client.sendall(bytes(message, encoding='utf-8'))
    if message == 'q':
        break
    ret = str(client.recv(1024), encoding='utf-8')
    print(ret)
client

三. 简单的ftp上传

  实现了将一个图片上传到服务器端

 1 # -*- coding:utf-8 -*-
 2 # zhou
 3 # 2017/7/2
 4 
 5 import socket
 6 
 7 server = socket.socket()
 8 server.bind(("127.0.0.1", 9998, ))  # 绑定ip
 9 server.listen(5)
10 
11 while True:
12     conn, address = server.accept()
13     # 连接之后首先接收文件大小
14     file_size = int(str(conn.recv(1024), encoding='utf-8'))
15     # 用来解决粘包问题的
16     conn.sendall(bytes("1001", encoding='utf-8'))
17     # 已经接受的文件大小
18     has_size = 0
19     num = 1
20     # 连接之后接收文件
21     f = open("new.jpg", 'wb')
22     while True:
23         num += 1
24         if file_size == has_size:
25             break
26         data = conn.recv(1024)
27         f.write(data)
28         has_size += len(data)
29     f.close()   # 关闭文件
ftpserver
 1 # -*- coding:utf-8 -*-
 2 # zhou
 3 # 2017/7/2
 4 
 5 
 6 import os
 7 import socket
 8 
 9 client = socket.socket()
10 
11 client.connect(("127.0.0.1", 9998), )
12 # 传送文件大小
13 file_size = os.stat("1.jpg").st_size
14 print(file_size)
15 # 发送文件大小
16 client.sendall(bytes(str(file_size), encoding='utf-8'))
17 client.recv(1024)   # 解决粘包问题
18 # 发送文件
19 with open("1.jpg", 'rb') as f:
20     for line in f:
21         client.sendall(line)
22 client.close()
ftpclient

四. 粘包问题的解决

  对于上面第三个ftp上传进行的描述,

  解决粘包的问题,当我们上传一个文件的时候,首先上传他的大小,当我们上传完大小之后要在写一句接受的语句,而服务器端在接受到文件大小之后要给我们立马发送一个数据用来确认,这样我们就可以完美的将数据喝大小分割开了。

  

原文地址:https://www.cnblogs.com/huwentao/p/7113483.html