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. Linux下设置Tomcat开机自启动

    --未验证 第一步:在/etc/init.d下新建一个文件tomcat(需要root操作权限) vi /etc/init.d/tomcat 然后点击"i"写下如下代码,tomcat ...

  2. java生成RSA公私钥字符串,简单易懂

    java生成RSA公私钥字符串,简单易懂   解决方法: 1.下载bcprov-jdk16-140.jar包,参考:http://www.yayihouse.com/yayishuwu/chapter ...

  3. spark中的cache和persist的区别

    在使用中一直知其然不知其所以然的地使用RDD.cache(),系统的学习之后发现还有一个与cache功能类似看起来冗余的persist 点进去一探究竟之后发现cache()是persist()的特例, ...

  4. React Native设置图片全屏背景显示

    显示效果如下: 实现和页面代码如下: 1> 使用的react-navigation隐藏导航栏: AddTopic: {screen: AddTopicScreen,navigationOptio ...

  5. 第十八章 并发登录人数控制——《跟我学Shiro》

    目录贴:跟我学Shiro目录贴 在某些项目中可能会遇到如每个账户同时只能有一个人登录或几个人同时登录,如果同时有多人登录:要么不让后者登录:要么踢出前者登录(强制退出).比如spring securi ...

  6. QT OpenGLWidget的surfaceFormat

    由OpenGLWidget和QOpenGLFunctions_2_0派生了类,试图使用双帧缓冲(Double Buffer)进行渲染.下面是部分功能代码: initializeGL()中: QSurf ...

  7. eclipse设置html js css自动提示

    eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用eclipse自带的插件,无需另外安装插件,具体步骤如下 1.打开eclipse→Window ...

  8. 在eNSP下使用Hybird接口

    1.实验拓扑图 2.实验编址表 3.实验过程 按照拓扑图设置各个PC机的IP地址 双击PC1然后弹出对话框,依次设置主机名:PC1→IP地址:192.168.1.1→子网掩码:255.255.255. ...

  9. JDK替换掉系统自带的gij编译工具

    解决办法: 在终端里面依次输入以下两句话 alternatives --install /usr/bin/java java /usr/java/jdk1.6.0_11/bin/java 300 al ...

  10. Linux基础重点习题讲解

    第一章  一个EXT4的文件分区,当时使用touch test.file命令创建一个新文件时报错,报错的信息是提示磁盘已满,但是采用df-h命令查看磁盘大小时,只使用了60%的磁盘空间,为什么会出现这 ...