Python之socket详解

Socket编程

1.基本概念

1.什么是客户端/服务器架构?
服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的“服务”。它存在唯一目的就是等待客户端的请求,
并响应它们(提供服务),然后等待更多请求。
说白了就是一个提供服务,一个请求服务得到相应的一个过程。

2.套接字:通信端点
套接字是计算机网络数据结构,它体现了上节中描述的“通信端点”的概念。在任何类型的通信开始之前,网络应用程序必须创建套接字。
可以将它们比作电话插孔,没有它将无法进行通信。

Python只支持AF_UNIX、AF_NETLINK、AF_TIPC 和 AF_INET ,重点使用基于网络的AF_INET.

3.套接字地址:主机-端口对
它是网络通信过程中端点的抽象表示,python使用元组保存:ADDR = (HOST,PORT)。

4.套接字类型
流式套接字(SOCK_STREAM):用于提供面向连接、可靠的数据传输服务。

数据报套接字(SOCK_DGRAM):提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。

2.Python网络编程

2.1 常见的套接字对象方法和属性

名 称 描 述
服务端 服务器套接字方法
s.bind(ADDR) 将地址(主机名、端口号对)绑定到套接字上
s.listen([backlog]) 设置并启动 TCP 监听器,如果指定backlog,则必须至少为0(如果低于0,则设置为0);
s.accept() 被动接受 TCP 客户端连接,一直等待直到连接到达(阻塞)
客户端 客户端套接字方法
s.connect() 主动发起 TCP 服务器连接
s.connect_ex() connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常
普通通用 普通的套接字方法
s.recv() 接收 TCP 消息
s.recv_into() 接收 TCP 消息到指定的缓冲区
s.send() 发送 TCP 消息
s.sendall() 完整地发送 TCP 消息
s.recvfrom() 接收 UDP 消息
s.recvfrom_into() 接收 UDP 消息到指定的缓冲区
s.sendto() 发送 UDP 消息
s.getpeername() 连接到套接字(TCP)的远程地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回给定套接字选项的值
s.setsockopt() 设置给定套接字选项的值
s.shutdown() 关闭连接
s.close() 关闭套接字
s.detach() 在未关闭文件描述符的情况下关闭套接字,返回文件描述符
s.ioctl() 控制套接字的模式(仅支持 Windows)
阻塞 面向阻塞的套接字方法
s.setblocking() 设置套接字的阻塞或非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 获取阻塞套接字操作的超时时间
文件方法 面向文件的套接字方法
s.fileno() 套接字的文件描述符
s.makefile() 创建与套接字关联的文件对象
属性 数据属性
s.family 套接字家族
s.type 套接字类型
s.proto 套接字协议

2.2 创建服务和客户端

2.2.1 创建TCP服务

一般的创建流程:

ss = socket()       #  创建服务器套接字
ss.bind(ADDR)       #  套接字与地址绑定
ss.listen()         #  监听连接
while True:         #  服务器无限循环
cs = ss.accept()    #  接受客户端连接
comm_loop:          #  通信循环
cs.recv()/cs.send() #  对话(接收 / 发送)
cs.close()          #  关闭客户端套接字
ss.close()          #  关闭服务器套接字 # (可选)
2.2.2 创建 TCP 客户端

一般的创建流程:

cs = socket()       #  创建客户端套接字
cs.connect()        #  尝试连接服务器
comm_loop:          #  通信循环
cs.send()/cs.recv() #  对话(发送 / 接收)
cs.close()          #  关闭客户端套接字
2.2.3 创建UDP服务

一般的创建流程:

ss = socket()       #  创建服务器套接字
ss.bind(ADDR)       #  套接字与地址绑定
while True:         #  服务器无限循环
ss.sendto()         #  发送
ss.recvfrom()       #  接收
ss.close()          #  关闭服务器套接字 # (可选)
2.2.4 创建 UDP 客户端

一般的创建流程:

cs = socket()       #  创建客户端套接字
comm_loop:          #  通信循环
cs.sendto()         #  发送
cs.recvfrom()       #  接收
cs.close()          #  关闭客户端套接字


server.py代码

import socket
from time import ctime
import json
import time
HOST = ‘‘
PORT = 9001
ADDR = (HOST, PORT)
BUFFSIZE = 1024
MAX_LISTEN = 5

def tcpServer():
    # TCP服务
    # with socket.socket() as s:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # 绑定服务器地址和端口
        s.bind(ADDR)
        # 启动服务监听
        s.listen(MAX_LISTEN)
        print(‘等待用户接入。。。。。。。。。。。。‘)
        while True:
            # 等待客户端连接请求,获取connSock
            conn, addr = s.accept()
            print(‘警告,远端客户:{} 接入系统!!!‘.format(addr))
            with conn:
                while True:
                    print(‘接收请求信息。。。。。‘)
                    # 接收请求信息
                    data = conn.recv(BUFFSIZE)
                    print(‘data=%s‘ % data)
                    print(‘接收数据:{!r}‘.format(data.decode(‘utf-8‘)))

                    # 发送请求数据
                    conn.send(data.encode(‘utf-8‘))
                    print(‘发送返回完毕!!!‘)
            s.close()

# 创建UDP服务
def udpServer():
    # 创建UPD服务端套接字
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        # 绑定地址和端口
        s.bind(ADDR)
        # 等待接收信息
        while True:
            print(‘UDP服务启动,准备接收数据。。。‘)
            # 接收数据和客户端请求地址
            data, address = s.recvfrom(BUFFSIZE)

            if not data:
                break

            print(‘接收请求信息:{}‘.format(data.decode(‘utf-8‘)))

            s.sendto(b‘i am udp,i got it‘, address)

        s.close()

if __name__ == ‘__main__‘:

    while True:
        choice = input(‘input choice t-tcp or u-udp:‘)

        if choice != ‘t‘ and choice != ‘u‘:
            print(‘please input t or u,ok?‘)
            continue

        if choice == ‘t‘:
            print(‘execute tcpsever‘)
            tcpServer()
        else:
            print(‘execute udpsever‘)
            udpServer()

client.py代码

import socket

from time import ctime
HOST = ‘localhost‘
PORT = 9001
ADDR = (HOST, PORT)
ENCODING = ‘utf-8‘
BUFFSIZE = 1024

def tcpClient():
    # 创建客户套接字
    with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as s:
        # 尝试连接服务器
        s.connect(ADDR)
        print(‘连接服务成功!!‘)
        # 通信循环
        while True:
            inData = input(‘pleace input something:‘)
            if inData == ‘q‘:
                break
            # 发送数据到服务器
            inData = ‘[{}]:{}‘.format(ctime(), inData)

            s.send(inData.encode(ENCODING))
            print(‘发送成功!‘)

            # 接收返回数据
            outData = s.recv(BUFFSIZE)
            print(‘返回数据信息:{!r}‘.format(outData))

        # 关闭客户端套接字
        s.close()

def udpClient():
    # 创建客户端套接字
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        while True:
            # 发送信息到服务器
            data = input(‘please input message to server or input \‘quit\‘:‘)
            if data == ‘quit‘:
                break
            data = ‘[{}]:{}‘.format(ctime(), data)

            s.sendto(data.encode(‘utf-8‘), ADDR)

            print(‘send success‘)

            # 接收服务端返回信息
            recvData, addrs = s.recvfrom(BUFFSIZE)

            print(‘recv message : {}‘.format(recvData.decode(‘utf-8‘)))

        # 关闭套接字
        s.close()

if __name__ == ‘__main__‘:

    while True:
        choice = input(‘input choice t-tcp or u-udp or q-quit:‘)
        if choice == ‘q‘:
            break
        if choice != ‘t‘ and choice != ‘u‘:
            print(‘please input t or u,ok?‘)
            continue

        if choice == ‘t‘:
            print(‘execute tcpsever‘)
            tcpClient()
        else:
            print(‘execute udpsever‘)
            udpClient()

代码说明:先执行 python server.py,在执行python client.py,就可以测试TPC/UDP简单的通信了。

原文地址:https://www.cnblogs.com/lonelyhiker/p/8577009.html

时间: 2024-10-16 07:12:04

Python之socket详解的相关文章

Python中dict详解

yangyzh Python中dict详解 python3.0以上,print函数应为print(),不存在dict.iteritems()这个函数. 在python中写中文注释会报错,这时只要在头部加上# coding=gbk即可 #字典的添加.删除.修改操作dict = {"a" : "apple", "b" : "banana", "g" : "grape", "o&qu

Python字符编码详解(转)

1. 字符编码简介 1.1. ASCII ASCII(American Standard Code for Information Interchange),是一种单字节的编码.计算机世界里一开始只有英文,而单字节可以表示256个不同的字符,可以表示所有的英文字符和许多的控制符号.不过ASCII只用到了其中的一半(\x80以下),这也是MBCS得以实现的基础. 1.2. MBCS 然而计算机世界里很快就有了其他语言,单字节的ASCII已无法满足需求.后来每个语言就制定了一套自己的编码,由于单字节

Python 字符串方法详解

Python 字符串方法详解 本文最初发表于赖勇浩(恋花蝶)的博客(http://blog.csdn.net/lanphaday),如蒙转载,敬请保留全文完整,切勿去除本声明和作者信息. 在编程中,几乎90% 以上的代码都是关于整数或字符串操作,所以与整数一样,Python 的字符串实现也使用了许多拿优化技术,使得字符串的性能达到极致.与 C++ 标准库(STL)中的 std::string 不同,python 字符串集合了许多字符串相关的算法,以方法成员的方式提供接口,使用起来非常方便. 字符

转:iOS中socket详解

一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象: 传输层.会话层.表示层和应用层则被称作主机层,是用户所面向和关心的内容. http协议   对应于应用层 tcp协议    对应于传输层 ip协议     对应于网络层 三者本质上没有可比性.  何况HTTP协议是基于TCP连接的. TCP/IP是传输层协议,主要解决数据如何在网络

python开发技术详解(二)

文章目录: 数据类型 数据类型 a=1 b=2 print id(a) print id(b) Out[1]: 163578032 Out[2]: 163578032 python开发技术详解(二)

Python之print详解

Python之print详解 http://www.jb51.net/article/55768.htm print的一些基本用法,在前面的讲述中也涉及一些,本讲是在复习的基础上,尽量再多点内容. eval() 在print干事情之前,先看看这个东东.不是没有用,因为说不定某些时候要用到. 复制代码 代码如下: >>> help(eval)      #这个是一招鲜,凡是不理解怎么用,就用这个看文档 Help on built-in function eval in module __b

转载:唐磊的个人博客《python中decorator详解》【转注:深入浅出清晰明了】

转载请注明来源:唐磊的个人博客<python中decorator详解> 前面写python的AOP解决方案时提到了decorator,这篇文章就详细的来整理下python的装饰器--decorator. python中的函数即objects 一步一步来,先了解下python中的函数. def shout(word='hello,world'):     return word.capitalize() + '!'print shout()#输出:Hello,world!#跟其他对象一样,你同样

windows上安装Anaconda和python的教程详解

一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因此,我们这里使用Python这个脚本语言来进行数字图像处理. 要使用Python,必须先安装python,一般是2.7版本以上,不管是在windows系统,还是Linux系统,安装都是非常简单的. 要使用python进行各种开发和科学计算,还需要安装对应的包.这和matlab非常相似,只是matla

【python进阶】详解元类及其应用2

前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使?type创建带有?法的类 最终你会希望为你的类增加?法.只需要定义?个有着恰当签名的函数并将 其作为属性赋值就可以了.添加实例?法 In [14]: def echo_bar(self):#定义了一个普通的函数 ...: print(self.bar) ...: In [15]: FooChild = type('