1 套接字socket

1.1 套接字概述

套接字,一种网络通讯工具;用于进行网络间的通信,是一种特殊文件类型,

套接字,是一个通信链的句柄,用于描述IP地址和端口,实现向网络发出请求或应答网络请求。

socket可以实现对文件的打开、读写和关闭模式操作,与file有相似之处

file模块是针对某个指定文件进行打开、读写和关闭操作的;

socket模块是对服务器和客户端socket进行打开、读写和关闭的操作。

1.2 套接字分类

流式套接字

按照字节流进行数据传输,提供面向连接的可靠的数据传输服务,TCP协议。

流式对数据来说是安全的,一次接受不完,下次还会继续接受。

数据报套接字

按照数据包进行数据的传输,提供无连接的不可靠的传输服务,UDP协议

原始套接字:底层套接字

注:

面向连接:在进行数据通信之前需要先建立服务端和客户端的连接,以确保消息传输的可靠性;不允许有数据的丢失的,一旦出现数据丢失,则认为数据不可靠,断开连接

面向无连接:数据发送前不需要确定连接关系,数据的发送是不可靠的,

1.3 TCP协议 (面向连接)

适用于: 传输质量要求高,数据传输量大,且需要可靠性

三次握手:

1.客户端向服务器端发起连接请求ack

2.服务器收到请求后确认允许连接,返回给客户端

3.客户端确认可连接后告知服务器准备发送消息

四次挥手:

1. 主动方告知被动方要断开连接

2. 接受到主动方请求后告知主动方已经接受到请求

3. 接收端处理完网络消息等工作后再次告知主动端可以断开

4. 主动方完成连接的断开

以确保发出的消息不会出现残留,传输一半的情况

1.4 UDP协议(面向无连接)

适用于:对消息可靠型没有严格要求,需要传输效率,网络状态不佳

2 基于TCP流式套接字过程

2.1 TCP服务器

主要有6步

1 创建套接字

2 绑定服务器IP端口

3 将套接字变为监听套接字,使可以接受tcp连接

4. 准备接受客户端连接

5 收发消息

6 关闭套接字

2.1.1 创建套接字(流式套接字)

socket(family = AF_INET,type = SOCK_STREAM,proto = 0)

功能:创建一个套接字

参数:

family:地址族类型

基于不同主机间的通信

AF_INET   IPv4(默认)

AF_INET6  IPv6

基于一台主机进程间的文件通讯

AF_UNIX    只能够用于单一的Unix系统进程间通信

type:套接字类型

SOCK_STREAM  流式套接字 TCP (默认)

SOCK_DGRAM   数据报套接字 UDP

proto:与特定的地址家族相关的协议

默认为0,此时系统就会根据地址格式和套接字类别,自动选择一个合适的协议

一般选择默认值0

返回值 : 返回一个套接字对象

2.1.2 绑定服务器IP、端口

sockfd.bind(address)

功能:绑定服务器的IP和端口

参数:address是一个元组(hostname, port)),第一个为字符串类型IP,第二个为数字类型端口号

示例 sockfd.bind('0.0.0.0',8888)

备注:socfkd为套接字句柄

2.3  监听套接字

sockfd.listen(backlog)

功能:开启TCP监听,创建监听队列,将套接字变为监听套接字。使其可以接受TCP连接

参数:backlog为正整数

备注:一个套接字可以连接很多客户端,不过瞬态只能连接一个(由于很快,所以无法模拟出来),处理完后再连接其他的;由于瞬态很快,所以可以理解为是一个队列。

2.1.4 准备接受客户端连接

sockfd.accept()

功能:阻塞等待客户端的连接,并一直处于等待状态

参数:无

返回值 :

第一个是一个与客户端通信的新的套接字
         第二个是连接进来的客户端的地址

2.1.5 收发消息

conn.recv(buffer)

功能:接受消息

参数:buffer:表示一次从缓冲区接受内容的大小

返回值:接受到的消息

conn.send() 
功能 : 发送消息

参数 : 要发送的消息

返回值 : 发送消息的大小

2.1.6 关闭套接字

sockfd.close()

2.2 TCP客户端

1 创建套接字

2 发起连接

3 收发消息

4 关闭套接字 

注意:在python3消息收发为byte,故遇到字符串需要编译

3 TCP套接字示例

套接字中的两个阻塞函数:

recv 和 send 为阻塞函数,

当缓冲区满时,执行send函数时会阻塞;

当缓冲区空时,执行recv函数时会阻塞

如果连接断开则recv会马上返回空字符串,结束阻塞

telnet 可以测试TCP套接字讯号通断,而不能检测UDP信号的情况

3.1 创建TCP服务器

import socket

HOST = '0.0.0.0'
PROT = 8888
ADDR = (HOST,PROT)

# 指定 Socket 接收缓冲区的大小
BUFFERSIZE = 1024

# 创建套接字
# 使用from socket import *全部导入后,可以直接去掉socket前缀
sockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 绑定服务器IP端口
sockfd.bind(ADDR)

# 将套接字变成监听套接字,使可以接受TCP连接
sockfd.listen(5)

# 准备接受客户端连接
print("wait for connect")
# conn 为一个与客户端通信的新的套接字
# addr 为连接进来的客户端的地址
conn,addr = sockfd.accept()
print("connect from",addr)

# 收发消息
data = conn.recv(BUFFERSIZE)
print(data.decode())

# 发送消息
num = conn.send("Receive your request".encode())
print(num)

# 关闭套接字
conn.close()
sockfd.close()

# 在python3消息收发为byte,而上面均是字符串,所以需要编译

3.2 创建TCP客户端

from socket import *

SERVER_HOST = '0.0.0.0'
SERVER_PORT = 8888
SERVER_ADDR = (SERVER_HOST,SERVER_PORT)

# 创建TCP套接字
# 同类型套接字可以连接,非同类套接字不可连接
sockfd = socket(AF_INET,SOCK_STREAM)

# 发起连接
sockfd.connect(SERVER_ADDR)

# 向服务器发送信息
sockfd.send(b'hello server')

# 接受服务器返回信息,缓冲区大小为1024
data = sockfd.recv(1024)
print(data)

# 关闭套接字
sockfd.close()

3.3 运行

(1)运行服务器

出现: wait for connect

(2)运行客户端

此时客户端出现: b'Receive your request'

同时服务器出现

connect from ('127.0.0.1', 57946)
hello server
20

注意事项:

(1)不能先运行客户端,否则会出现 ConnectionRefusedError

Traceback (most recent call last):
  File "t_c.py", line 12, in <module>
    sockfd.connect(SERVER_ADDR)
ConnectionRefusedError: [Errno 111] Connection refused

找不到服务器,无法运行代码。

(2)连续运行服务器时,会出现 Address already in use

Traceback (most recent call last):
  File "t_s.py", line 15, in <module>
    sockfd.bind(ADDR)
OSError: [Errno 98] Address already in use

连续运行服务器时,原端口尚没有释放,所以会出现 address 被占用情况。

解决方案:

(a)出现address被占用时,暂停一会再执行,等待端口从缓冲区释放

(b)再运行服务器前修改端口号: SERVER_PORT = 8888 比如改成9999等之类

(c) setsockopt(SOL_SOCKET,SO_REUSEADDR,1) ,将其设置为1,端口可重用,可以再重新启用。

4 沾包

沾包的定义:

在TCP流式套接字中,发送方发送的若干数据被接收方一次性接受,就好像一条数据一样粘连在一起,这种现象为数据沾包

(1)在文件传输过程中沾包是不需要处理的

(2)如果发送的每一条消息都有特定的意义,此时需要考虑沾包带来的影响

沾包的形成:

也即,粘包形成的必要条件,

(1)流式套接字

(2)接受的没有发送的快

沾包的解决:

解决沾包的方案:

(1)格式化数据

(2)发送数据时指明数据长度

(3)每次发送有一个时间间隔,一般而言,相隔0.1秒足够了,但该方法不适合数据量较大的、频繁发送的情况;该方法使用也较少。

4 数据报套接字UDP

4.1 关键字

sockfd.recvfrom()

功能:接受网络消息

参数:buffersize

返回值 :

data:接收到的消息

addr:消息来源的ADDRESS

每次recvfrom接受一个数据报,即使接受不全就会使其他数据丢失

sockfd.sendto()

功能:发送消息

参数:

data:要发送的消息

addr:将消息发送给谁

sendall() 和send()基本相同,试图发送所有消息,发送成功返回None,失败则报出异常
sendall()和sendto不一样,不能替代sendto

4.2 服务器(UDP数据报套接字)

(1)创建数据报套接字

(2)绑定IP和端口

(3)接受发送消息

(4)关闭套接字

4.3 客户端(UDP数据报套接字)

与TCP数据流套接字类似。

5 UDP套接字示例

5.1 服务器(UDP)

from socket import *
from time import *

HOST = '127.0.0.1'
PORT = 8888
ADDR = (HOST,PORT)
BUDDERSIZE = 1024

# 创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

# 绑定IP端口
sockfd.bind(ADDR)

while True:

    # 接受发送消息
    data, addr = sockfd.recvfrom(BUDDERSIZE)
    print('recv from ',addr)

    # 发送消息
    sockfd.sendto(('%s:[%s]'%(ctime(),data)).encode(),addr)

# 关闭套接字
sockfd.close()

5.2 客户端(UDP)

from socket import *
import sys

# sys.argv 从外设获取的迭代对象并返回列表
# sys.argv[0]为路径
# 少于三个元素则退出运行
if len(sys.argv) <3:
    print('argv is error')
    sys.exit(1)

# 获取IP地址
HOST = sys.argv[1]
#从终端获得的为字符串,需转换成整形
PORT = int(sys.argv[2])
ADDR = (HOST,PORT)
BUFFERSIZE = 1024

# 创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

while True:
    data = input(">>")
    if not data:
        break
    # 发送消息,第一元素为发送内容,ADDR为内容接受的地址
    sockfd.sendto(b"hello udp server",ADDR)
    data, addr = sockfd.recvfrom(BUFFERSIZE)
    print(data.decode())

# 关闭套接字
sockfd.close()

5.3 运行

1 先运行服务器,实际上没有任何显示

2 运行客户端

注意:

(a)由于客户端 len(sys.argv) > 3 的限制,所以必须输入三个元素以上才不会使程序运行结束

(b)t_c.py、‘127.0.0.1’、‘8888’三个元素中间必须用空格隔开,如果连在一起则会认为一个元素

(c)IP(‘127.0.0.1’)和端口('8888')必须与服务器名称一致, 否则 sockfd.sendto(b"hello udp server",ADDR) 中的ADDR找不到服务器

3 向客户端中输入内容

6 sys.argv()

示例:文件名s_argv.py

import sys

if len(sys.argv) <3:
    print('argv is error')
    sys.exit(1)
print(sys.argv)
print(sys.argv[1])
print(sys.argv[2])

运行: python3 s_argv.py

结果: argv is error

因为 len(sys.argv) < 3  所以会直接结束 sys.exit(1)

再运行结果

python3 s_argv.py '
#直接显示结果
[']
127.0.0.1
8888

再运行

python3 s_argv.py a 12
[']
a
12

详细信息可参考Python中 sys.argv[]的用法简明解释

7 TCP与UDP对比

UDP 比 TCP 更加适合提供循环服务

循环服务方式不适合传输时间过长,一个客户端需要长期占用服务器的情况,TCP连接则需要持续连接占用服务器。

8 套接字属性

套接字对象的属性

conn.getpeername() # 得到连接端的addr

sockfd.getsockname() # 获取套接字对应主机的信息

sockfd.type  # 测试套接字类型

getsockopt(level,optname) # 获取值

setsockopt(level,optname,value) # 设置值

setsockopt(SOL_SOCKET,SO_REUSEADDR,1) # 让套接字端口可以重用,当套接字结束时,可以再重新启用

pythonl练习笔记——PythonNet 套接字socket的更多相关文章

  1. 网络协议学习笔记(五)套接字Socket

    概述 前面学习网络知识的时候写过一篇关于套接字的随笔见<JAVA SOCKET 详解>,现在本人正在系统的学习网络知识,现在除了温故知新之外,在详细的学习记录一下套接字的知识. Socke ...

  2. think in java 读书笔记 2 —— 套接字

    目录 think in java 读书笔记 1 ——移位 think in java 读书笔记 2 —— 套接字 think in java 读书笔记 3 —— 数据报 概要 1. 套接字基本知识 2 ...

  3. Linux进程间通信(八):流套接字 socket()、bind()、listen()、accept()、connect()、read()、write()、close()

    前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进程.通常我们使用socket进行网络编 ...

  4. Linux进程间通信(九):数据报套接字 socket()、bind()、sendto()、recvfrom()、close()

    前一篇文章,Linux进程间通信——使用流套接字介绍了一些有关socket(套接字)的一些基本内容,并讲解了流套接字的使用,这篇文章将会给大家讲讲,数据报套接字的使用. 一.简单回顾——什么是数据报套 ...

  5. 套接字socket 的地址族和类型、工作原理、创建过程

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

  6. [置顶] Java套接字Socket编程

    1)概念 网络编程基本模型就客户端到服务器的模型,也就是我们常见的C/S模型.简单的说就是两个进程间相互通信的过程.即通信双方一方作为服务器等待客户端提出请求并给以回应,另一方作为客户端向服务器提出请 ...

  7. Java网络编程--套接字Socket

    一.套接字Socket IP地址标志Internet上的计算机,端口号标志正在计算机上运行的进程(程序). 端口号被规定为一个16位的0--65535之间的整数,其中,0--1023被预先定义的服务通 ...

  8. 套接字编程,创建套接字socket

    1.套接字地址结构: struct sockaddr { sa_family_t sa_family; char sa_data[14]; }; 其中,成员sa_family表示套接字的协议族类型,对 ...

  9. 什么是套接字(Socket)

    应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要 通过同一个TCP协议端口传输数据.为了区别不同的应用程序进程和连 ...

随机推荐

  1. 基于zabbix 的memached 多实例监控

    基于zabbix 的memached 多实例监控 zabbix agentd 配置文件新增配置: UserParameter=memcached.server.discovery[*],ps uax ...

  2. EventBus 事件总线 原理 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. 浅谈Java两种并发类型——计算密集型与IO密集型

    转载:https://blog.csdn.net/u013070853/article/details/49304099 核心是可以分别独立运行程序指令的计算单元.线程是操作系统能够进行运算调度的最小 ...

  4. INSTALL_FAILED_MISSING_SHARED_LIBRARY

    target选项中要选择Google APIs.如图.

  5. Shell或notepad连接虚拟机操作

    首先在linux终端中查看自己的ip:ifconfig -a 一.Xshell的配置如下: 上图中: 处填写的是昵称,方便记住这个会话连接的是哪个系统. 要选择SSH,因为安装的是OpenSSH 处填 ...

  6. iOS多线程与网络开发之多线程NSThread

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  7. Apache+Tomcat负载均衡集群搭建

    1.所需软件 apache_2.2.4-win32-x86-no_ssl.apacheserver mod_jk-apache-2.2.4连接器,连接apache和tomcat apache-tomc ...

  8. 玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)

    杂家前文曾写过一篇关于仅仅拍摄特定区域图片的demo.仅仅是比較简陋.在坐标的换算上不是非常严谨,并且没有完毕预览界面四周暗中间亮的效果,深以为憾.今天把这个补齐了. 在上代码之前首先交代下,这里面存 ...

  9. 【安卓】给gallery内&quot;控件&quot;挂载事件,滑动后抬起手指时也触发事件(滑动时不应触发)的解决、!

    思路: 1.gallery内控件挂载事件(如:onClickListener)的方法类似listview,可直接在baseAdapter.getView内给控件挂载(详细方法百度). 2.貌似没问题, ...

  10. IP共享重新验证

    大家在进入共享机器的时候,在运行窗口中输入了 \\IP 然后会有账户和密码验证, 有时为了方便选择了记忆密码账号,这样下次就不会再验证了. 但是,有时你当时输入的账户没有你需要打开的某个文件的权限,就 ...