1、初识socket

经过近一个半月的学习我们已经度过了python基础的阶段,今天我们开始学习python网络编程,没有难以理解的逻辑,更注重的是记忆。

对网络协议和基础没有概念的可以在阅读本文前预习计算机基础3、网络协议:http://www.cnblogs.com/liluning/p/7170799.html

一、客户端/服务器架构

1、C/S结构,即Client/Server(客户端/服务器)结构

2、我们在互联网中处处可见c/s架构比如说浏览器,qq,lol,视频软件。。。

3、我们学习socket就是为了c/s架构的开发



二、scoket与网络协议

首先我们需要实现网络通信必然需要多网络协议有着深刻的了解。而我们做开发如果把每一点都搞清楚太过于耗费精力,所以我们才有了scoket

socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的



三、套接字

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

1、基于文件类型的套接字:AF_UNIX

unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

2、基于网络类型的套接字:AF_INET

还有AF_INET6被用于ipv6,还有一些其他的地址家族,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET

3、套接字函数的认识

首先我们要知道所有的函数使用都需要导入socket模块

1)socket()模块

import socket
获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

2)服务端套接字函数

bind()    绑定(主机,端口号)到套接字
listen()  开始TCP监听
accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

3)客户端套接字函数

connect()     主动初始化TCP服务器连接
connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

4)公共用途的套接字函数

recv()            接收TCP数据
send()            发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
sendall()         发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
recvfrom()        接收UDP数据
sendto()          发送UDP数据
getpeername()     连接到当前套接字的远端的地址
getsockname()     当前套接字的地址
getsockopt()      返回指定套接字的参数
setsockopt()      设置指定套接字的参数
close()           关闭套接字

5)面向锁的套接字函数

setblocking()     设置套接字的阻塞与非阻塞模式
settimeout()      设置阻塞套接字操作的超时时间
gettimeout()      得到阻塞套接字操作的超时时间

6)面向文件的套接字函数

fileno()          套接字的文件描述符
makefile()        创建一个与该套接字相关的文件


四、基于tcp的套接字代码实现

前面一次性近二十个函数是不是看蒙蔽了 来看看实际应用其实应用很简单

tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

tcp服务端

ss = socket()      #创建服务器套接字
ss.bind()      #把地址绑定到套接字
ss.listen()      #监听链接
while True :      #服务器无限循环
    conn,client_addr=ss.accept()      #接受客户端链接
    while True :      #通讯循环
        conn.recv()/cs.send()      #对话(接收与发送)
    conn.close()      #关闭客户端套接字
ss.close()      #关闭服务器套接字(可选)

tcp客户端

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

1、socket通信流程与打电话流程类似以此为例:

服务端:

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #买手机
s.bind(‘127.0.0.1‘,8080)  #手机插卡
s.listen(5)  #开机

#print(‘starting...‘)
conn,addr=s.accept()  #等电话 (链接,客户的的ip和端口组成的元组)
#print(conn,addr)

data=conn.recv(1024)  #接收
print(‘client data: <%s>‘ %data)
conn.send(data.upper())  #发送

conn.close()  #挂电话
s.close()  #关机

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect((‘127.0.0.1‘,8080)) #绑定手机卡

#发,收消息
phone.send(‘hello‘.encode(‘utf-8‘))
data=phone.recv(1024)
print(‘server back res:<%s>‘ %data)

phone.close()

2、加上链接循环与通信循环

服务端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.bind((‘127.0.0.1‘,8081)) #绑定手机卡
phone.listen(5) #开机 最多挂起5个服务

print(‘starting...‘)
while True: #链接循环
    conn,client_addr=phone.accept() #等电话 (链接,客户的的ip和端口组成的元组)
    print(‘-------->‘,conn,client_addr)

    #收,发消息
    while True:#通信循环
        try:
            data=conn.recv(1024)
            if not data:break #针对linux
            print(‘client data: <%s>‘ %data)
            conn.send(data.upper())
        except Exception:
            break
    conn.close() #挂电话
phone.close() #关机

客户端(可以有几个客户端一起链接后面的被挂起前一个断开后立马链接):

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect((‘127.0.0.1‘,8081)) #绑定手机卡

#发,收消息
while True:
    msg=input(‘>>: ‘).strip()
    if not msg:continue
    phone.send(msg.encode(‘utf-8‘))
    data=phone.recv(1024)
    print(‘server back res:<%s>‘ %data)

phone.close()

3、模拟ssh远程模拟命令

服务端:

import socket
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind((‘127.0.0.1‘,8082))
phone.listen(5)

print(‘starting...‘)
while True:
    conn,client_addr=phone.accept()
    print(‘-------->‘,conn,client_addr)

    while True:
        try:
            cmd=conn.recv(1024)
            #if not cmd:break #针对linux
            #执行cmd命令,拿到cmd的结果,结果应该是bytes类型
            #。。。。
            res = subprocess.Popen(cmd.decode(‘utf-8‘), shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout=res.stdout.read()
            stderr=res.stderr.read()

            #发送命令的结果
            conn.send(stdout+stderr)
        except Exception:
            break
    conn.close() #挂电话
phone.close() #关机

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((‘127.0.0.1‘,8082))

while True:
    cmd=input(‘>>: ‘).strip()
    if not cmd:continue
    phone.send(cmd.encode(‘utf-8‘))
    cmd_res=phone.recv(1024)
    print(cmd_res.decode(‘gbk‘))
phone.close()


五、异常解决(了解)

解决方法:

#加入一条socket配置,重用ip和端口

phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind((‘127.0.0.1‘,8080))

发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
vi /etc/sysctl.conf

编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30

然后执行 /sbin/sysctl -p 让参数生效。

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;

net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。

net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

linux系统方法



六、subprocess模块(简单介绍)

允许你去创建一个新的进程让其执行另外的程序,并与它进行通信,获取标准的输入、标准输出、标准错误以及返回码等

Popen类

subprocess模块中定义了一个Popen类,通过它可以来创建进程,并与其进行复杂的交互。查看一下它的构造函数:

__init__(self, args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None, preexec_fn=None,
close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None,
creationflags=0)

主要参数说明: 
args:args should be a string, or a sequence of program arguments.也就是说必须是一个字符串或者序列类型(如:字符串、list、元组),用于指定进程的可执行文件及其参数。如果是一个序列类型参数,则序列的第一个元素通常都必须是一个可执行文件的路径。当然也可以使用executeable参数来指定可执行文件的路径。

stdin,stdout,stderr:分别表示程序的标准输入、标准输出、标准错误。有效的值可以是PIPE,存在的文件描述符,存在的文件对象或None,如果为None需从父进程继承过来,stdout可以是PIPE,表示对子进程创建一个管道,stderr可以是STDOUT,表示标准错误数据应该从应用程序中捕获并作为标准输出流stdout的文件句柄。

shell:如果这个参数被设置为True,程序将通过shell来执行。 
env:它描述的是子进程的环境变量。如果为None,子进程的环境变量将从父进程继承而来。

实例化:

res = subprocess.Popen(r‘dir‘, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
时间: 2024-10-10 01:02:01

1、初识socket的相关文章

二、网编之初识Socket套接字结构体

二.初识Socket套接字结构体 1.通用套接字结构体类型 struct sockaddr { sa_family_t sa_family; //协议簇 char sa_data[14]; //协议簇数据 } 通用套接字结构体可以在不同的协议簇之间进行强制转化,Socket网络编程中几乎所有套接字API函数的形参都是通用套接字结构体struct sockaddr. 存在问题: 通用套接字结构体对编程的角度来说,设置很不方便,我们以以太网协议来说,当要设置端口号.IP地址等,那么我需要将端口号与I

初识Socket通信:基于TCP和UDP协议学习网络编程

学习笔记: 1.基于TCP协议的Socket网络编程: (1)Socket类构造方法:在客户端和服务器端建立连接 Socket s = new Socket(hostName,port);以主机名和端口号作为参数来创建一个Socket对象. Socket s = new Socket(address,port);以InetAddress对象和端口号作为参数来创建一个Socket对象. 创建Socket对象时可能抛出UnknownHostException或IOException异常,必须捕获它们

初识socket

socket也叫套接字,用于通信的一个句柄,描述IP与端口信息,程序通过套接字可以向网络发出请求或者应答网络请求. socket起源与unix,而unix/Linux基本哲学之一就是”一切皆文件“,对于文件用[打开],[关闭],[读写]模式来操作, socket是该模式的一个实现,socket是一种特殊的文件,一切socket函数就是对其进行的操作(读/写IO,打开,关闭) file模块是针对某个指定文件进行打开,读写,关闭操作 socket模块是针对 服务端与客户端socket 进行打开,读写

android 初识socket通信--java程序做服务器

1.新建一个java工程做服务器 public class MyServer { String str ; public MyServer(){ try { //服务器端的声明用serversocket,括号里面写端口号,端口号是自己指定的 ServerSocket ss = new ServerSocket(4700); //accept方法在这里会一直等待客户端连接进来 Socket accept = ss.accept(); //新建一个读入流,字符集是utf-8 BufferedRead

python之路——初识socket

一.socket模块的常用方法: 1.AF_UNIX:一台机器直接的通信 2.AF_INET:基于网络的通信 3.socket.socket():获取套接对象 4.listen:监听链接数量 5.accept:等待客户端链接 6.connect:链接服务端 7.socket.SOCK_DGRAM:数据流 8.socket.SOCK_STREAM:tcp协议,也是一个数据流 9.send:发送消息 10.recv:接收消息 11.decode:解码 12.encode:编码 13.SO_REUSE

循序渐进Python3(八) -- 初识socket

socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是"一切皆文件",对于文件用[打开][读写][关闭]模式来操作. socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: file模块是针对

网络编程&lt;&lt;初识socket&gt;&gt;

楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好.但是如果这两个程序之间想要传递一个数据,你要怎么做呢?这个问题以你现在的知识就可以解决了,我们可以创建一个文件,把a.py想要传递的内容写到文件中,然后b.py从这个文件中读取内容就可以了 但是当你的a.py和b.py分别在不同电脑上的时候,你要怎么办呢?**类似的机制有计算机网盘,qq等等.我们可以在我们的电脑上和别人聊天,可以在自己的电脑

初识Socket通讯编程(一)

一.什么是socket? 当两台计算机需要通信的时候,往往我们使用的都是TCP去实现的,但是并不会直接去操作TCP协议,通常是通过Socket进行tcp通信.Socket是操作系统提供给开发者的一个接口,通过它,就可以实现设备之间的通信. 二.TCP是如何通信的? TCP连接和断开分别会存在3次握手/4此握手的过程,并且在此过程中包含了发送数据的长度(接受数据的长度),无容置疑,这个过程是复杂的,这里我们不需要做深入的探讨.如果有兴趣,可以参考此文章,这里详细的解释了TCP通信的过程: http

python进阶---Python中的socket编程(一)

初识socket编程 一.前言 socket基于C\S架构(客户端\服务端)的编程模型,在Python中是以socket模块存在的. Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议. 所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规