【socket通信】python实现简单socket通信| server和client

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

参考内容:
1)TCP/IP网络通信之Socket编程入门

一、socket通信基础知识

1.1基础知识

socket又名套接字。
socket启动需要的基础信息:进行通信的主机号端口号。(端口号其实代表了进程,也就是主机上的哪一个应用程序会进行通信)
socket就像数据线一样连接于两个电脑之间,作为通信的桥梁。

1.2socket类型

socket一般有两种类型:TCP和UDP
TCP:Transmission Control Protocol 传输控制协议
TCP协议是可靠的,发送的数据对方一定会收到。TCP是基于数据流的协议(data stream).
UDP:User Datagram Protocol 用户报文协议
UDP是不可靠的,不一定保证数据一定能被对方接收到。UDP一般具有更低的延迟并且会占用更少的资源(适合语音通话)

以下内容是根据chatGPT所捕获的TCP和UDP的知识点:

TCP和UDP是两种不同的网络传输协议。TCP (Transmission Control Protocol) 是一种面向连接的协议,它建立一个可靠的连接,然后在连接上发送数据。UDP (User Datagram Protocol) 是一种无连接的协议,它不保证数据的可靠传输。TCP协议在传输数据之前需要进行三次握手,建立连接后,数据传输的可靠性较高,但是传输效率较低。UDP协议不需要建立连接,传输效率较高,但是无法保证数据的可靠性。
TCP协议适用于需要可靠数据传输的场景,例如电子邮件、文件传输、网页浏览等。UDP协议适用于需要快速传输的场景,例如音频、视频流等。

二、socket python实现

2.1.服务器代码 server.py

import socket

# 创建socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取本地主机名和端口号
host = socket.gethostname()
port = 8888

# 将socket对象绑定到指定的主机和端口上
server_socket.bind((host, port))

# 开始监听连接
server_socket.listen(1)

# 等待客户端连接
print("等待客户端连接...")
client_socket, client_address = server_socket.accept()

print("连接来自: ", client_address)

# 接收客户端发送的数据
data = client_socket.recv(1024)

# 处理接收到的数据
print("接收到的数据为: ", data.decode())

# 发送响应数据给客户端
message = "欢迎连接到服务器!"
client_socket.send(message.encode())

# 关闭客户端连接
client_socket.close()

1)socket.gethostname()和socket.gethostbyname()是不一样的:
socket.gethostname()获取当前主机的主机名,以便在Socket连接中进行使用。如果你想要使用IP地址而不是主机名来进行Socket连接,可以使用socket.gethostbyname()函数来获取主机的IP地址。
2)关于端口号
一旦通过socket.bind()方法将一个socket对象绑定到一个IP地址和端口号上,这个socket对象就会被分配一个唯一的端口号。这个端口号可以用来发送和接收数据,从而实现Socket通信。
当客户端想要连接到这个服务器时,客户端需要知道服务器的IP地址和端口号。客户端通过这个端口号来建立Socket连接,并与服务器进行通信,从而实现数据的传输和交换。因此,端口号是Socket通信中非常重要的一个概念。
这个端口号是为这个socket对象而生的。
3)server_socket.accept()
server_socket.accept()会阻塞程序运行,直到有客户端连接进来。一旦有客户端连接进来,accept()方法就会返回一个新的socket对象client_socket和该客户端的地址信息client_address。
通过client_socket可以和该客户端进行通信,而client_address包含了该客户端的IP地址和端口号,可以用于标识该客户端的身份。

2.2.客户端代码 client.py

import socket

# 创建socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取服务器的主机名和端口号
host = socket.gethostname()
port = 8888

# 连接到服务器
client_socket.connect((host, port))

# 发送消息给服务器
message = "Hello, 服务器!"
client_socket.send(message.encode())

# 接收服务器发送的响应数据
data = client_socket.recv(1024)

# 处理接收到的响应数据
print("接收到的数据为: ", data.decode())

# 关闭客户端连接
client_socket.close()

1)与服务器代码的不同之处:
与服务器代码相比,客户端代码的主要区别在于它使用了socket.connect()方法连接到服务器,并使用socket.send()方法发送消息给服务器,而服务器代码则使用socket.bind()方法绑定一个IP地址和端口号,并使用socket.listen()方法监听客户端连接请求,然后使用socket.accept()方法接受客户端连接,并使用socket.recv()方法接收客户端发送的消息。
2)message.encode()
message.encode()是Python中字符串的一个方法,用于将字符串编码为字节序列。在Python中,字符串是以Unicode编码存储的,而网络传输中常使用字节序列来传输数据,因此需要将字符串编码为字节序列才能在网络上传输。
message.encode()方法将字符串message按照默认的编码方式(通常是UTF-8编码)编码为字节序列,并返回一个bytes类型的对象。这个bytes对象可以直接传输给socket的send()方法发送到网络中。在接收端,需要将接收到的字节序列使用相应的解码方法(如bytes.decode()方法,这个在服务器程序中出现过)解码为字符串。

2.3.如何运行

使用方法:分别用两个终端cmd运行两个py文件(先服务器后客户端),最后得到的结果如下:
服务器:
在这里插入图片描述

客户端:
在这里插入图片描述

以上代码肯定对于初学者会衍生出来不少问题
1)客户端的端口号应该设置成什么样子?
在Socket通信中,端口号是用来标识服务器程序或客户端程序的。在服务器程序中,我们需要指定一个端口号,以便客户端程序可以连接到该端口上进行通信。通常情况下,我们可以选择一些预定义的端口号,例如HTTP协议的端口号是80,SMTP协议的端口号是25等。但是,如果预定义的端口号已经被占用或者不适合我们的应用程序,我们也可以选择自定义端口号。
在你提供的代码中,端口号是自定义的,可以根据需要进行设置。一般情况下,我们可以选择一些未被占用的端口号,例如8888。
2)相应之下,是不是客户端的端口号也需要设置为相同的值?

如果服务器的端口号设置为8888,那么客户端在连接服务器时也需要指定端口号为8888。这样客户端才能够连接到正确的端口上,与服务器进行通信。在Socket通信中,端口号是用来标识服务器程序或客户端程序的,因此在客户端和服务器之间进行通信时,端口号必须保持一致才能够成功建立连接。

补充的计网知识

部分答案来自chatgpt
1)特殊地址:127.0.0.1

127.0.0.1是一个特殊的IP地址,也称为本地回环地址。它指向本机的网络接口,也就是说,当你访问这个地址时,实际上是在访问本机自己。这个地址通常用于测试网络应用程序,以及在本机上安装一些服务器软件时,可以使用这个地址进行测试。例如,当你在本机上安装了一个Web服务器,可以使用浏览器访问127.0.0.1来测试Web服务器是否正常工作。
2)
host = socket.gethostbyname(socket.gethostname()) 和host="127.0.0.1"是不是一个意思?
host = socket.gethostbyname(socket.gethostname()) 和 host=“127.0.0.1” 不完全相同,虽然它们都可以用于指定本机的IP地址。
socket.gethostbyname(socket.gethostname()) 会返回当前主机的IP地址,这个地址可以是一个局域网IP地址,也可以是一个公网IP地址。如果你的电脑连接了一个局域网,那么这个IP地址就可以用于在局域网内进行通信。
host=“127.0.0.1” 则表示使用本机的回环地址(loopback address),也就是127.0.0.1。这个地址是一个特殊的IP地址,它只能在本机内部使用,不能用于在局域网或公网进行通信。
在上述代码中,使用 socket.gethostbyname(socket.gethostname()) 可以获取本机的IP地址,这样就可以在局域网内进行通信。如果你只是在本机内部进行通信,也可以使用 host=“127.0.0.1”。

3)进程间通信和socket通信的区别
进程间通信和Socket通信是两种不同的通信方式,它们的实现机制和应用场景都有所不同。
进程间通信(IPC,Inter-Process Communication)是指在同一台计算机上运行的不同进程之间进行通信的机制,主要用于实现同一计算机上不同应用程序之间的数据传输。IPC机制可以通过命名管道(named pipe)、共享内存、消息队列、信号量等方式来实现,它们的实现都是通过操作系统提供的API来实现的。IPC通信的优点是速度快、可靠性高,但是只能在同一台计算机上进行通信。
Socket通信是一种基于网络的通信方式,它是通过一组标准的TCP/IP协议来实现的,可以在不同计算机之间实现数据传输。Socket通信是一种面向连接的通信方式,通信的过程中需要建立连接、传输数据、断开连接等步骤,因此它的实现比IPC要复杂一些。Socket通信的优点是可以在不同的计算机之间进行通信,可以实现跨网络的数据传输,但是相对于IPC,Socket通信的速度会稍微慢一些。
总之,进程间通信和Socket通信都有各自的优缺点,需要根据具体的应用场景来选择合适的通信方式。如果只需要在同一台计算机上进行通信,可以选择IPC机制;如果需要在不同的计算机之间进行通信,可以选择Socket通信。

4)socket通信和网络通信是一个概念吗

Socket通信和网络通信是相关的概念,但并不完全等同。
网络通信是指通过计算机网络进行数据传输的过程,包括了多种不同的通信方式和协议,例如TCP/IP、HTTP、FTP等。网络通信的目的是将数据从一个计算机传输到另一个计算机,使得不同计算机之间可以互相传递信息。
Socket通信是一种基于网络的通信方式,它是通过一组标准的TCP/IP协议来实现的。在Socket通信中,数据传输需要经过网络协议栈的处理,其中TCP/IP协议是最常用的网络协议之一。Socket通信是一种面向连接的通信方式,通信的过程中需要建立连接、传输数据、断开连接等步骤,因此它的实现比其他网络通信方式要复杂一些。
因此,可以说Socket通信是网络通信的一种具体实现方式,它是通过TCP/IP协议来实现的。网络通信涵盖了多种不同的通信方式和协议,而Socket通信是其中一种实现方式。

5)字符串编码和字节序列是?
当我们需要在网络上传输数据时,需要将数据编码为字节序列,才能通过网络进行传输。而在Python中,字符串是以Unicode编码存储的,因此需要将字符串编码为字节序列才能在网络上传输。
下面是一个例子,将字符串编码为字节序列:

s = “hello world”
b = s.encode()

print(b) # b’hello world’

在这个例子中,我们先定义了一个字符串s,然后使用s.encode()方法将其编码为字节序列b,并将其打印出来。输出结果是b’hello world’,表示字符串"hello world"已经被编码为一个bytes类型的对象。
当接收方接收到字节序列后,需要将其解码为字符串才能进行处理。下面是一个将字节序列解码为字符串的例子:

b = b’hello world’
s = b.decode()

print(s) # hello world

在这个例子中,我们先定义了一个字节序列b,然后使用b.decode()方法将其解码为字符串s,并将其打印出来。输出结果是hello world,表示字节序列b’hello world’已经被解码为字符串"hello world"。

猜你喜欢

转载自blog.csdn.net/weixin_46274756/article/details/130146222