socket介绍

1、什么是socket

  socket是应用层与传输层中间的一个软件抽象层,它是一组接口。它把TCP/IP这些复杂的协议统一封装起来

  这样我们只要知道如何使用socket就好,就已经符合了传输层往下的一大串协议

2、为什么要使用socket

  如果没有socket而我们写的代码又要让别人能正确解析,就需要一层层往下研究协议,写出符合协议的代码

  而我们大家传输层往下的代码基本一样,所以把这些代码封装成一个模块,方便大家使用,不用去考虑传输层

  以下的东西

3、socket发展

  套接字起源于20世纪70年代,一开始,套接字被设计用在同一台主机上多个应用程序的通讯,这也被称为

  进程间通讯或者IPC。后来网络发展,又被应用于网络协议上。

  套接字有两种(或者称为有两个种族):

    基于文件类型的套接字家族:名字  --> AF_UNIX

    基于网络类型的套接字家族:名字  --> AF_INET被用于ipv4       AF_INET6被用于ipv6

socket用法

# 需要明确的是:

  关于网络协议和socket相关概念,对于所有编程语言都是一致的,区别仅仅是个编程语言的函数名称不同

1、服务器端

import socket
# 获得socket对象 AF_INET表示基于网络的套接字
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# SOCK_STREAM表示的是TCP协议 SOCK_DGRAM表示的是UDP协议
# 将socket对象绑定ip地址和端口号
sk.bind(('127.0.0.1',8080)) # 参数需要传入一个元组
# 相当于电话的开机 括号里的参数表示可以同时接收5个请求
sk.listen(5) # 一般服务器都不需要关闭,所以加个while循环
while True:
# 进入监听状态,等待别人链接过来,有两个返回值,一个是对方的socket对象,一个是对方的ip以及端口
client,addr = sk.accept()
# 收发消息一般都需要多次循环发送,也加个while循环
while True:
try: # 如果对面强行关闭,为了程序不崩,就需要异常处理
msg = client.recv(1024) # recv表示接收,括号里是最大接收字节
if not msg: # 如果接收到的消息是空字符串,就表示对面正常退出,需要打断循环
break
# send表示发送数据,发送的数据必须是二进制数据
client.send('二进制数据'.encode('utf-8'))
except Exception as e:
print(e)
break
client.close() # 关闭对面传过来的对象
sk.close() # 关闭服务器的socket对象

2、客户端

import socket
# 获取socket对象,括号里默认是AF_INET 和 SOCK_STREAM 所以可以不写
sk = socket.socket()
# 链接到服务器端 括号里也是一个元组,包含ip地址以及对方的端口号
sk.connect(('127.0.0.1',8080)) # 自己的端口号系统会随机分配,不需要设置 while True: # 收发信息也需要循环
try: # 为了防止服务器非正常下线而导致客户端直接崩溃,需要加入异常处理
cmd = input('>>(q:退出)')
if cmd == 'q': # 给客户端一个可以正常退出的方法
break
if not cmd: # 如果直接敲回车,那么cmd就是空字符串,TCP协议对此进行优化
continue # 正常收发消息过程中,你传入空字符串,它不会帮你发送
sk.send(cmd.encode('utf-8'))
# 如果上面没有做空判断,输入空会直接跳过send这步,这样客户端和服务器端都处于接收状态,卡住不动
sk.recv(1024)
except Exception as e:
print(e)
break
sk.close() # 关闭socket对象

3、基于TCP的socket通讯流程图

socket常见问题

1、端口占用

报错信息

Traceback (most recent call last):
File "F:/pyprogram/day31/homework/topic2/test.py", line 6, in <module>
sk.bind(('127.0.0.1',8080))
OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

问题发生的原因

  1.可能是由于你已经启动了服务器程序,却又再次启动了服务器程序,同一个端口不能被多个进程使用导致

  2.三次握手或四次挥手时,发生了异常导致对方程序已经结束而服务器任然处于time_wait状态导致

  3.在高并发的场景下,由于连接的客户端太多,也会产生大量处于time_wait状态连接

解决的方案

  第一种重新选择端口后就可以,或者把之前的占用端口的进程关闭掉

  第二三种以后再说

2、强行关闭链接

报错信息

Traceback (most recent call last):
File "F:/pyprogram/day31/part2/客户端.py", line 12, in <module>
client.send(msg.encode('utf-8'))
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

问题发生的原因

  当客户端与服务器链接成功后,如果一方没有执行close,而是直接强行终止程序(或是遇到异常被迫终止)

  都会导致另一方发生问题

  在windows下,接收数据的一方在recv函数处将抛出异常

解决的方案

  用try...except语法抓取异常,抓到对方强退异常后并处理

3、客户端正常结束,服务器端无限循环空字符

报错信息

  不会产生报错信息,但是服务器端会一直循环空字符串

问题发生的原因

  客户端正常close()之后,会给服务器发送一个空字符串,

  如果服务器端没有发送数据的话,就会一直循环接收这个空字符串,占用CPU资源

解决的方案

  在服务器端接收的地方加上空字符串判断,如果是空字符串,就表示对方客户端退出了

  那么判断空成功,让自己也退出循环

socket基本用法的更多相关文章

  1. Java中的Socket的用法

                                   Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...

  2. Java语言Socket接口用法详解

    Socket接口用法详解   在Java中,基于TCP协议实现网络通信的类有两个,在客户端的Socket类和在服务器端的ServerSocket类,ServerSocket类的功能是建立一个Serve ...

  3. 第一篇 网站基础知识 第4章 Java中Socket的用法

    第4章 Java中Socket的用法 4.1 普通Socket的用法 Java中的网络通信是通过Socket实现的,Socket分为ServetSocket和Socket两大类,ServetSocke ...

  4. 2015-12-27 socket的用法

    sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) sk.bind(address) s.bind(address) 将套接字绑定到地址.a ...

  5. JAVA中Socket的用法模拟服务端和客户端

    <看透springMvc源代码分析与实践>学习笔记 Socket分为ServerSocket和Socket两个大类 ServerSocket用于服务端,可以通过accept方法监听请求,监 ...

  6. 通过编写聊天程序来熟悉python中多线程及socket的用法

    1.引言 Python中提供了丰富的开源库,方便开发者快速就搭建好自己所需要的应用程序.本文通过编写基于tcp/ip协议的通信程序来熟悉python中socket以及多线程的使用. 2.python中 ...

  7. setsockopt 设置socket 详细用法

    1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:BOOL bReuseaddr=TRUE;setsockopt(s,SOL_SOCKET ,SO ...

  8. 【android】Socket简单用法

    Socket通常也称做”套接字“,用于描述IP地址和端口,废话不多说,它就是网络通信过程中端点的抽象表示.值得一提的是,Java在包java.net中提供了两个类Socket和ServerSocket ...

  9. setsockopt 设置socket 详细用法(转载)

    转自:http://www.cppblog.com/killsound/archive/2009/01/16/72138.html 1.closesocket(一般不会立即关闭而经历TIME_WAIT ...

随机推荐

  1. ELK 二进制安装并收集nginx日志

    对于日志来说,最常见的需求就是收集.存储.查询.展示,开源社区正好有相对应的开源项目:logstash(收集).elasticsearch(存储+搜索).kibana(展示),我们将这三个组合起来的技 ...

  2. HTML5 地理位置定位API(2)

    HTML5 Geolocation API (地理位置应用程序接口) 目前PC浏览器支持情况: Firefox 3.5+Chrome 5.0+Safari 5.0+Opera 10.60+Intern ...

  3. iOS 越狱后OpenSSH安装报错

    转载自:https://www.jianshu.com/p/75f6d0f54d61 安装OpenSSH报错 尝试重启手机重新安装 将手机语言设置为英文状态 将手机设置为飞行模式,用wifi下载(我的 ...

  4. 学习 TTreeView [15] - 连接数据库 (作为给 "丁永其" 和 "DELPHI万岁" 两位朋友的回复)

    本例效果图: unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Contro ...

  5. python reduce和偏函数partial

    functools模块 reduce方法: reduce方法 reduce方法,顾名思义就是减少 可迭代对象不能为空,初始值没提供就在可迭代对象中去一个元素 from functools import ...

  6. pycharm 对mysql的可视化操作

    参照: https://blog.csdn.net/qq_24189933/article/details/75666243

  7. 使用json_encode编码中文返回null的解决方案

    在gbk的程序中,直接使用json_encode编码包含中文字符的数组,将会返回null. 解决方法: 1.把程序文件编码改为utf8 2.使用mb_convert_encoding把编码转换为utf ...

  8. GraphQL学习之原理篇

    前言 在上一篇文章基础篇中,我们介绍了GraphQL的语法以及类型系统,算是对GraphQL有个基本的认识.在这一篇中,我们将会介绍GraphQL的实现原理.说到原理,我们就不得不依托于GraphQL ...

  9. Hadoop概念学习系列之Hadoop、Spark学习路线

    1 Java基础: 视频方面:          推荐<毕向东JAVA基础视频教程>.学习hadoop不需要过度的深入,java学习到javase,在Java虚拟机的内存管理.以及多线程. ...

  10. Python函数或者类的时间参数的默认值设为datetime.date.today()引起的问题

    定义了函数def main(start_date=datetime.date.today(), end_date=datetime.date.today()): pass 函数在项目启动后, end_ ...