澳门新浦京电子游戏PHP Socket 编程过程详解

本文由码农网 –
小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

socket简介

套接字

1.网络通信协议

介绍

Socket用于进程间通信。进程间通信通常基于客户端—服务端模型。此时,客户端—服务端是可以彼此交互的应用程序。客户端和服务端之间的交互需要连接。Socket编程负责的就是为应用程序之间建立可进行交互的连接。

在本文中,我们将学习如何用PHP创建一个简单的客户端—服务端。我们还将学习如何客户端应用程序如何发送消息到服务端,以及如何从服务端接受消息。

澳门新浦京电子游戏 1

1.本地的进程间通信(IPC)有很多种方式,例如

• 队列
• 同步(互斥锁、条件变量等)
以上通信方式都是在一台机器上不同进程之间的通信方式,那么问题来了
网络中进程之间如何通信?

  osi七层模型:按照分工不同把互联网协议从逻辑上划分了层级

使用代码

目的:开发一个客户端用于发送string消息到服务端,服务端将相同的信息反转后返回给客户端。

PHP服务器

第1步:设置变量,如“主机”和“端口”

$host = "127.0.0.1";
$port = 5353;
// No Timeout 
set_time_limit(0);

端口号可以是1024 -65535之间的任何正整数。

第2步:创建socket

$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socketn");

第3步:绑定socket到端口和主机

创建的socket资源绑定到IP地址和端口号。

$result = socket_bind($socket, $host, $port) or die("Could not bind to socketn");

第4步:启动socket监听

在绑定到IP和端口后,服务端开始等待客户端的连接。在没有连接之前它就一直等下去。

$result = socket_listen($socket, 3) or die("Could not set up socket listenern");

第5步:接受连接

这个函数会接受所建的socket传入的连接请求。在接受来自客户端socket的连接后,该函数返回另一个socket资源,实际上就是负责与相应的客户端socket通信。这里的“$spawn”就是负责与客户端socket通信的socket资源。

$spawn = socket_accept($socket) or die("Could not accept incoming connectionn");

到现在为止,我们已经准备好了服务端socket ,但实际上这个脚本并没有做任何事情。所以为了继续完成上述目标,我们将读取客户端socket消息,然后将接收到的消息反转后发回给客户端socket。

第6步:从客户端socket读取消息

$input = socket_read($spawn, 1024) or die("Could not read inputn");

第7步:反转消息

$output = strrev($input) . "n";

第8步:发送消息给客户端socket

socket_write($spawn, $output, strlen ($output)) or die("Could not write outputn");

关闭socket

socket_close($spawn);
socket_close($socket);

这就完成了服务端。现在,我们学习如何创建PHP客户端。

PHP客户端

前两个步骤与服务端相同。

第1步:设置变量,如“主机”和“端口”

$host = "127.0.0.1";
$port = 5353;
// No Timeout 
set_time_limit(0);

注:这里的端口和主机应该和服务端中的定义是相同的。

第2步:创建socket

$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socketn");

第3步:连接到服务端

$result = socket_connect($socket, $host, $port) or die("Could not connect toservern");

此时和服务端不同,客户端socket不绑定端口和主机。相反,它连接到服务端socket,等待接受来自客户端socket的连接。这一步建立了客户端socket到服务端socket的连接。

第4步:写入服务端socket

socket_write($socket, $message, strlen($message)) or die("Could not send data to servern");

在此步骤中,客户端socket的数据被发送到服务端socket。

第5步:阅读来自服务端的响应

$result = socket_read ($socket, 1024) or die("Could not read server responsen");
echo "Reply From Server  :".$result;

第6步:关闭socket

socket_close($socket);

完整的代码

服务端(server.php)

// set some variables
$host = "127.0.0.1";
$port = 25003;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socketn");
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bind to socketn");
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket listenern");

// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming connectionn");
// read client input
$input = socket_read($spawn, 1024) or die("Could not read inputn");
// clean up input string
$input = trim($input);
echo "Client Message : ".$input;
// reverse client input and send back
$output = strrev($input) . "n";
socket_write($spawn, $output, strlen ($output)) or die("Could not write outputn");
// close sockets
socket_close($spawn);
socket_close($socket);

客户端(client.php)

$host    = "127.0.0.1";
$port    = 25003;
$message = "Hello Server";
echo "Message To server :".$message;
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socketn");
// connect to server
$result = socket_connect($socket, $host, $port) or die("Could not connect to servern");  
// send string to server
socket_write($socket, $message, strlen($message)) or die("Could not send data to servern");
// get server response
$result = socket_read ($socket, 1024) or die("Could not read server responsen");
echo "Reply From Server  :".$result;
// close socket
socket_close($socket);

建立上述文件(server.php和client.php)后,执行如下操作:

  1. 复制www目录中的这些文件(假设WAMP),安置于C:澳门新浦京电子游戏,wamp。
  2. 打开Web浏览器,在地址栏中键入localhost 。
  3. 先浏览server.php然后client.php。
2. 网络中进程之间如何通信

首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!
在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。
其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。
这样利用ip地址,协议,端口就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互

澳门新浦京电子游戏 2

许可证

这篇文章,以及任何相关的源代码和文件,是经过The Code Project Open
License (CPOL)许可的。

3. 什么是socket

socket(简称 套接字)
是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于
Socket 来完成通信的
例如我们每天浏览网页、QQ 聊天、收发 email 等等

  1. 创建socket
    在 Python 中 使用socket 模块的函数 socket 就可以完成:
    socket.socket(AddressFamily, Type)
    说明:
    函数 socket.socket 创建一个 socket,返回该 socket
    的描述符,该函数带有两个参数:
    • Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者
    AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
    • Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP
    协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
    创建一个tcp socket(tcp套接字)
    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print ‘Socket Created’

澳门新浦京电子游戏 3

创建一个udp socket(udp套接字)
   import socket

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    print 'Socket Created'

  socket层

UDP介绍

UDP —
用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

澳门新浦京电子游戏 4

UDP特点:

UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。
UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。
UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

2.理解socket:

【适用情况】

UDP是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP一般用于多点通信和实时的数据业务,比如
• 语音广播
• 视频
• QQ
• TFTP(简单文件传送)
• SNMP(简单网络管理协议)
• RIP(路由信息协议,如报告股票市场,航空信息)
• DNS(域名解释)

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

注重速度流畅

UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。

套接字socket历史:

udp网络程序-发送数据

socket函数
mySocket = socket(family, type)

函数socket()的参数family用于设置网络通信的域,函数socket()根据这个参数选择通信协议的族。通信协议族在文件sys/socket.h中定义。

澳门新浦京电子游戏 5

Paste_Image.png

函数socket()的参数type用于设置套接字通信的类型,主要有SOCKET_STREAM(流式套接字)、SOCK——DGRAM(数据包套接字)等。
并不是所有的协议族都实现了这些协议类型,例如,AF_INET协议族就没有实现SOCK_SEQPACKET协议类型。

澳门新浦京电子游戏 6

Paste_Image.png

创建一个udp客户端程序的流程是简单,具体步骤如下:

  1. 创建客户端套接字
  2. 发送/接收数据
  3. 关闭套接字

      from socket import *
  1. 创建套接字
    udpSocket = socket(AF_INET, SOCK_DGRAM)
  2. 准备接收方的地址
    sendAddr = (‘192.168.11.74’, 7788)
  3. 从键盘获取数据
    sendData = input(“请输入要发送的数据:”)
  4. 发送数据到指定的电脑上
    udpSocket.sendto(sendData.encode(‘gbk’), sendAddr)
  5. 关闭套接字
    udpSocket.close()

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

udp 网络程序-端口问题

澳门新浦京电子游戏 7

Paste_Image.png

说明:

每重新运行一次网络程序,上图中红圈中的数字,不一样的原因在于,这个数字标识这个网络程序,当重新运行时,如果没有确定到底用哪个,系统默认会随机分配

记住一点:这个网络程序在运行的过程中,这个就唯一标识这个程序,所以如果其他电脑上的网络程序如果想要向此程序发送数据,那么就需要向这个数字(即端口)标识的程序发送即可

  基于文件类型的套接字家族: 

udp绑定信息

一般情况下,在一天电脑上运行的网络程序有很多,而各自用的端口号很多情况下不知道,为了不与其他的网络程序占用同一个端口号,往往在编程中,udp的端口号一般不绑定
但是如果需要做成一个服务器端的程序的话,是需要绑定的,想想看这又是为什么呢?
如果报警电话每天都在变,想必世界就会乱了,所以一般服务性的程序,往往需要一个固定的端口号,这就是所谓的端口绑定

  套接字家族的名字:AF_UNIX

绑定示例
    #coding=utf-8

    from socket import *

    #1. 创建套接字
    udpSocket = socket(AF_INET, SOCK_DGRAM)

    2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配
    bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
    udpSocket.bind(bindAddr)

    #3. 等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

    #4. 显示接收到的数据
    print(recvData)

    #5. 关闭套接字
    udpSocket.close()

总结

一个udp网络程序,可以不绑定,此时操作系统会随机进行分配一个端口,如果重新运行次程序端口可能会发生变化

一个udp网络程序,也可以绑定信息(ip地址,端口号),如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的

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

udp广播

TCP/IP协议栈中, 传输层只有UDP可以广播.

澳门新浦京电子游戏 8

Paste_Image.png

  基于网络类型的套接字家族:

udp总结

  1. udp是TCP/IP协议族中的一种协议能够完成不同机器上的程序间的数据通信
  2. udp服务器、客户端

    udp的服务器和客户端的区分:往往是通过请求服务和提供服务来进行区分
    • 请求服务的一方称为:客户端
    • 提供服务的一方称为:服务器
  3. udp绑定问题

    一般情况下,服务器端,需要绑定端口,目的是为了让其他的客户端能够正确发送到此进程

    客户端,一般不需要绑定,而是让操作系统随机分配,这样就不会因为需要绑定的端口被占用而导致程序无法运行的情况

  套接字家族的名字:AF_INET

udp综合作业-模拟QQ

任务要求:
• 使用多线程完成一个全双工的QQ聊天程序
单工、半双工、全双工
单工数据传输只支持数据在一个方向上传输;
半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力.

  AF_INET6被用于ipv6,还有一些其他的地址家族,不过,基本没用,所有地址家族中,AF_INET是使用最广泛的一

,python支持多种地址家族,不过我们主要用网络编程,所以主要还是AF_INET

3.基于TCP和UDP两个协议下socket的通讯

  TCP(Transmission Control
Protocol)可靠的、面向连接的协议、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

  UDP(User Datagram
Protocol)不可靠的、无连接的服务,传输效率高,一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 ;视频流;IP语音。

澳门新浦京电子游戏 9

tcp协议下的socket:

  服务器端先初始化Socket,然后与端口绑定,对端口进行监听,调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器,如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

澳门新浦京电子游戏 10

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

基本代码:

server端

 1 import socket 2 sk = socket.socket() 3 sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字 4 sk.listen()          #监听链接 5 conn,addr = sk.accept() #接受客户端链接 6 ret = conn.recv  #接收客户端信息 7 print       #打印客户端信息 8 conn.send(b'hi')        #向客户端发送信息 9 conn.close()       #关闭客户端套接字10 sk.close()        #关闭服务器套接字

client端

1 import socket2 sk = socket.socket()           # 创建客户套接字3 sk.connect(('127.0.0.1',8898))    # 尝试连接服务器4 sk.send(b'hello!')5 ret = sk.recv         # 对话6 print7 sk.close()            # 关闭客户套接字

相关bug:

1.socket绑定IP和端口时可能出现下面的问题:不让重复使用端口

澳门新浦京电子游戏 11

澳门新浦京电子游戏 12澳门新浦京电子游戏 13

 1 #加入一条socket配置,重用ip和端口 2 import socket 3 from socket import SOL_SOCKET,SO_REUSEADDR 4 sk = socket.socket() 5 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #在bind前加,允许地址重用 6 sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字 7 sk.listen()          #监听链接 8 conn,addr = sk.accept() #接受客户端链接 9 ret = conn.recv   #接收客户端信息10 print              #打印客户端信息11 conn.send(b'hi')        #向客户端发送信息12 conn.close()       #关闭客户端套接字13 sk.close()        #关闭服务器套接字

View 解决办法 Code

若任然报错,出现OSError: [WinError
10013]
以一种访问权限不允许的方式做了一个访问套接字的尝试
。那么只能换端口了,因为你的电脑不支持端口重用。

2.远程主机强迫关闭了一个先有连接

澳门新浦京电子游戏 14

这是由于强制断开造成的,解决很简单,谁依赖于谁,先关掉依赖者,再关闭被依赖者就好;还有一种是和多个连接造成,tcp协议下最好一对一,一对多可见下面代码。

澳门新浦京电子游戏 15澳门新浦京电子游戏 16

 1 import socket 2  3 server = socket.socket() 4 ip_port = ('127.0.0.1',8081) 5 server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  # 固定写法,允许地址重用,若还报错OSerror,系统原因,改端口 6  7 server.bind 8 server.listen()  # 监听 可跟参数 n 代表监听n+1次 如,listen,意思是我连接着一个,后面还有3排队,共4个. 9 10 while 1:11     conn,addr = server.accept()  # 阻塞等待连接12     while 1:13         server_msg = input('>>>>> ')14         server_msg = server_msg.encode('utf-8')15         conn.send(server_msg)  # 发消息16         if server_msg == 'byebye':  # 多个客户端连接时,结束前一个后,跳出当前循环到上一个while,重新获得连接17             break18 19         from_client_msg = conn.recv  # 接消息20         from_client_msg = from_client_msg.decode('utf-8')21         if from_client_msg == 'byebye':22             break23         print('来自客户端的消息:',from_client_msg)24     conn.close()

View 一对多_服务端
Code澳门新浦京电子游戏 17澳门新浦京电子游戏 18

 1 import socket 2  3 client = socket.socket() 4 server_ip = ('127.0.0.1',8081) 5 client.connect(server_ip) 6  7 while 1: 8     from_server_msg = client.recv(1024) 9     from_server_msg = from_server_msg.decode('utf-8')10     print('来自服务器>>>',from_server_msg)11     if from_server_msg == 'byebye':12         break13 14     client_msg = input('>>>>> ')15     client_msg = client_msg.encode('utf-8')16     client.send(client_msg)17     if client_msg == 'byebye':18         break19 20 client.close()

View 一对多_客户端
Code澳门新浦京电子游戏 19澳门新浦京电子游戏 20

 1 # 再来一份即可 2 import socket 3  4 client = socket.socket() 5 server_ip = ('127.0.0.1',8081) 6 client.connect(server_ip) 7  8 while 1: 9     from_server_msg = client.recv(1024)10     from_server_msg = from_server_msg.decode('utf-8')11     print('来自服务器>>>',from_server_msg)12     if from_server_msg == 'byebye':13         break14 15     client_msg = input('>>>>> ')16     client_msg = client_msg.encode('utf-8')17     client.send(client_msg)18     if client_msg == 'byebye':19         break20 21 client.close()

View 一对多_客户端01 Code

总结:用socket进行通信,必须是一收一发对应好。

udp协议下的socket

*  服务器端先初始化Socket,然后与端口绑定,recvform接收消息,这个消息有两项,消息内容和对方客户端的地址,然后回复消息时也要带着你收到的这个客户端的地址,发送回去,最后关闭连接,一次交互结束。*

澳门新浦京电子游戏 21

注意:udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接,但在发消息时要跟上地址。

基本 代码:

server端

1 import socket2 udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字3 udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字4 msg,addr = udp_sk.recvfrom(1024)5 print6 udp_sk.sendto(b'hi',addr)                 # 对话7 udp_sk.close()                         # 关闭服务器套接字

client端:

1 import socket2 ip_port=('127.0.0.1',9000)3 udp_sk=socket.socket(type=socket.SOCK_DGRAM)4 udp_sk.sendto(b'hello',ip_port)5 back_msg,addr=udp_sk.recvfrom(1024)6 print(back_msg.decode('utf-8'),addr)

4.练习代码:

#  用户登录作业用tcp协议下的socket写:
#  1. 服务端
#     - 等待客户端来发送数据:用户名、密码
#     - 本地文件中查看用户名密码是否合法。
#     - 合法:登录成功
#     - 否则:用户名或密码错误

#  2. 客户端
#     - 用户输入:用户名、密码
#     - 发送到服务端进行校验。

澳门新浦京电子游戏 22澳门新浦京电子游戏 23

 1 import socket 2 import time 3  4 server = socket.socket() 5 ip_port = ('127.0.0.1',8083) 6 server.bind 7 server.listen() 8 conn,addr = server.accept()  # 等待conn 9 10 dic = {'张三':'123','赵四':'345','王八':'567'}11 12 client_msg = conn.recv(1024)13 client_msg = client_msg.decode('utf-8')  # 还原成字典14 client_msg = eval(client_msg)15 print(client_msg)16 time.sleep(5)17 18 for k in dic:19     if {k:dic[k]} == client_msg:20         conn.send('登录成功!'.encode('utf-8'))21     else:22         conn.send('用户名或密码错误!'.encode('utf-8'))

View 服务端
Code澳门新浦京电子游戏 24澳门新浦京电子游戏 25

 1 import socket 2  3 client = socket.socket() 4 server_ip = ('127.0.0.1',8083) 5 client.connect(server_ip) 6  7 k = input('请输入账户:') 8 v = input('请输入密码:') 9 # 存入字典,发送给服务端10 msg = {k:v}11 client.send.encode('utf-8'))12 13 from_server_msg = client.recv(1024)14 print(from_server_msg.decode('utf-8'))

View 客户端 Code

# udp协议下的socket聊天工具
#  1. 服务端
#     - 接收客户端发送的信息并作出回复。
#     - 检查是否有某些指定关键字并回复消息,如果发送过来的消息中还有sb字符串,那么将sb替换成alexsb,然后和你要输入的内容组合起来发送给客户端。
#  2. 多个客户端
#     - 客户端向服务端发送信息

澳门新浦京电子游戏 26澳门新浦京电子游戏 27

 1 import socket 2  3 talk_server = socket.socket(type=socket.SOCK_DGRAM) 4 ip_port = ('127.0.0.1',8086) 5 talk_server.bind 6  7 while 1: 8     from_client_msg,addr = talk_server.recvfrom(1024) 9     from_client_msg = from_client_msg.decode('utf-8')10     print('来自客户端>>>',from_client_msg)11     if from_client_msg == 'byebye':12         break13 14     msg = input('>>> ')15     if 'sb'in from_client_msg:16         msg2 = from_client_msg.replace('sb', 'alexsb')17         talk_server.sendto(.encode('utf-8'),addr)18     else:19         talk_server.sendto(msg.encode('utf-8'), addr)20 21 talk_server.close()

View 服务端
Code澳门新浦京电子游戏 28澳门新浦京电子游戏 29

 1 # udp下复制多个以下代码即可实现多客户端  2  3 import socket 4  5 talk_client = socket.socket(type=socket.SOCK_DGRAM) 6 server_ip_port = ('127.0.0.1',8086) 7  8 while 1: 9     msg = input('>>>')10     if msg == 'byebye':11         break12     msg = msg.encode('utf-8')13     talk_client.sendto(msg,server_ip_port)14 15     from_server_msg,addr = talk_client.recvfrom(1024)16     print('来自服务端>>>',from_server_msg.decode('utf-8'))17 18 talk_client.close()

View 客户端 Code

5.缓冲区:

# 缓冲区: socket对象 在接收和发送数据时都是先放到缓冲区,再到目标地址的,这样可避免网络延迟、数据丢包等.

socket缓冲区解释:

每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。

write
并不立即向网络传数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是TCP协议负责的事情。

TCP协议独立于 write
函数,数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。

read 函数也是如此,也从输入缓冲区中读取数据,而不是直接从网络中读取。

  

发表评论

电子邮件地址不会被公开。 必填项已用*标注