socket的使用(UDP、TCP)代码部分

用udp模拟客户端:

声明:其实udp并不强调服务器与客户端的关系,通常来说服务器需要绑定端口,而客户端不需要绑定端口,而是在使用时候操作系统随便的给一个。UDP通信属于帧传输,TCP则是流传输,在帧传输过程中对于消息的次序和到达情况没有需求,所以UDP属于不可靠传输,不需要确认和排序。这样在客户端和服务器的实现上就没有太大的差别了。

需要的工具:在网上下载一个  网络调试助手

主要是用来模拟客户端、服务器啥的。里面可以选择3中类型(udp tcp_server tcp_client)

我们先选择UDP

模拟客户端的代码如下:

由于流程在代码注释在写的很详细、这里不再重复:

"""
主要是使用udp协议,连接模拟的服务器,发送消息、接收消息的过程

主要步骤:

1.创建套接字

2.提供服务器的ip地址、和端口号

3.发送数据、接受数据

4.关闭套接字
"""
import socket

class UdpClient(object):
	# 初始化:需要提供一个元组包含服务器的ip地址和端口号
	# 其中ip地址是字符串、端口号是数字
	# 在初始化中需要创建一个udp套接字
	def __init__(self):
		print("第一步先创建一个套接字")
		self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

	def set_ip_port(self):
	    # 其中ip地址是字符串、端口号是数字
		print("")
		print("----------------------------")
		print("第二步,设置ip和port")
		server_ip = input("请输入服务器的ip地址: ")
		server_port = int(input("请输入服务器的port号: "))
		self.add_info = (server_ip, server_port)

	def send_mes(self):
		print("")
		print("----------------------------")
		print("第三步,向服务器发送消息")
		you_mes = input("请输入要发送给服务器的消息: ")
		self.udp_socket.sendto(you_mes.encode("utf-8"), self.add_info)

	def recv_mes(self):
		print("")
		print("----------------------------")
		print("第四步,等待接收服务器发送的消息")
		# recvfrom返回的是一个元组,第一个元素是对方发送的数据,第二个是一个小元组,里面是服务器的ip地址和端口号
		recv_data = self.udp_socket.recvfrom(1024)  # 1024表示字节大小,
		# 打印接受到的消息
		print(recv_data[0].decode("gbk"))      # win是以GBK的编码方式编码的
		print(recv_data[1])

	def close_socket(self):
		print("")
		print("----------------------------")
		print("第五步,关闭套接字")
		self.udp_socket.close()

def main():
	# 创建一个udp客户端,
	my_udp_client = UdpClient()

	# 调用set_ip_port方法设置要发送和接受消息的服务器的ip 和 port
	my_udp_client.set_ip_port()

	# 给服务器发送消息
	my_udp_client.send_mes()

	# 等待接受服务器的消息,如果服务器一直没有发送消息,程序会一直卡在这里,也就是堵塞在这里。
	# 直到服务器发送消息过来,就会解堵塞,程序运行结束
	my_udp_client.recv_mes()

	# 关闭套接字
	my_udp_client.close_socket()


if __name__ == "__main__":
	main()

执行部分:

1.首先打开网络助手选择udp

2.点击连接下面的按钮(连接)

3.在linux终端下执行这个程序:

如下:

补充:如果我们在发送和接受消息部分、让循环,就可以实现一个简单的聊天器,不过由于recvfrom存在堵塞的情况,所以只能发一条,收一条。

但是我们使用多任务不管是进程、线程、和协程的方式,我们就能解决这个问题、让一个任务一直在跑发送消息、让一个任务一直在跑接收消息。

下面用udp绑定 ip和端口(假定我们写的程序作为服务器吧)

程序代码如下:跟上面的代码换汤不换药

需要注意的是在用网络助手的时候需要将绑定的端口号输入正确:

"""
主要是使用udp协议,假定创建一个服务器,而网络助手充当客户端

主要步骤:

1.创建套接字

2.绑定ip 和端口

3.发送数据、接受数据

4.关闭套接字
"""
import socket

class UdpServer(object):
	# 在初始化中需要创建一个udp套接字
	def __init__(self):
		print("创建一个套接字")
		self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		self.ip_port = ("192.168.49.1", 8080)

	def bind_ip_port(self):
		print("")
		print("----------------------------")
		print("绑定ip和port")
		self.udp_socket.bind(("", 8899))

	def send_mes(self):
		print("")
		print("----------------------------")
		print("向客户端发送消息")
		you_mes = input("请输入要发送给客户端的消息: ")
		# 我的win上的ip和地址为别如下:我们也可以等客户端发送消息过来捕捉到它的ip和端口然后
		# 我们将ip port存储起来,在也行

		self.udp_socket.sendto(you_mes.encode("gbk"), self.ip_port)

	def recv_mes(self):
		print("")
		print("----------------------------")
		print("等待接收客户端发送的消息")
		# recvfrom返回的是一个元组,第一个元素是对方发送的数据,第二个是一个小元组,里面是服务器的ip地址和端口号
		recv_data = self.udp_socket.recvfrom(1024)  # 1024表示字节大小,
		# 打印接受到的消息
		print(recv_data[0].decode("gbk"))      # win是以GBK的编码方式编码的
		print(recv_data[1])

	def close_socket(self):
		print("")
		print("----------------------------")
		print("第五步,关闭套接字")
		self.udp_socket.close()

def main():
	# 创建一个udp服务器,
	my_udp_srever = UdpServer()

	# 调用set_ip_port方法设置要发送和接受消息的服务器的ip 和 port
	my_udp_srever.bind_ip_port()

	
	# 等待接受客户端的消息,如果客户端一直没有发送消息,程序会一直卡在这里,也就是堵塞在这里。
	# 直到客户端发送消息过来,就会解堵塞,程序运行结束
	my_udp_srever.recv_mes()

	# 给客户端发送消息
	my_udp_srever.send_mes()

	# 关闭套接字
	my_udp_srever.close_socket()


if __name__ == "__main__":
	main()

TCP模拟客户端:

要注意的是:套接字在接收消息的时候只会接收字符串,不是一个元组了,不会有发送方(服务器)的ip port

因为你连接的时候已经知道了;

"""
程序的主要功能:

创建一个使用tcp协议,进行收发数据的客户端版本,让网络助手充当服务器

实现的主要步骤:

1.创建一个tcp的套接字

2.在连接服务器之前给定服务器的Ip和port号

3.connect服务器

4.将要发送的信息发送给服务器

5.接收服务器发送的消息

6.关闭套接字

"""
import socket


class TcpClient(object):
	def __init__(self):
		# 创建套接字
		self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		
		# 初始化要连接的 ip port
		self.server_ip = input("请输入要连接的服务器的ip: ")
		self.server_port = int(input("请输入要连接的服务器的port: "))

	def con_server(self):
		# 使用conect连接服务器:函数接收的是元组
		self.tcp_socket.connect((self.server_ip, self.server_port))


	def send_mes(self):
		# 向服务器发送消息
		send_data = input("输入向服务器发送的消息:")
		self.tcp_socket.send(send_data.encode("utf-8"))

	def recv_mes(self):
		# 接收服务器的消息,注意接收的不是元组,不会接收服务器的ip port 原因是:连接的时候已经知道了
		recv_data = self.tcp_socket.recv(1024)
		print("服务器发送的消息是: ",recv_data.decode("gbk"))
	
	def close_socket(self):
		self.tcp_socket.close()



def main():
	# 创建一个tcpclient对象
	tcp_client = TcpClient()

	# 连接服务器
	tcp_client.con_server()

	# 发送消息
	tcp_client.send_mes()

	# 接收消息
	tcp_client.recv_mes()

	# 关闭套接字
	tcp_client.close_socket()



if __name__ == "__main__":
	main()

TCP模拟服务器:

"""
明确程序目标: 模拟使用tcp协议的 服务器端

步骤流程:

1.创建套接字

2.绑定端口 ip port

3.将主动设置为被动状态:监听套接字,这样就能被别人连接

4.等待客户端的连接:accept(),没有客户端连接就会一直堵塞、知道有客户端到来才会解堵塞
	会产生一个专门为此时连接的客户端服务的套接字。这样监听套接字就能继续监听其他客户端的连接

5.发送和接收消息

"""
import socket


class TcpServer():
	def __init__(self):
		print("---------开始初始化---------")
		self.judge = False  # 主要是用来退出当前客户服务的循环
		self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		# 对于服务器来说绑定一件很重要的事,所以我在初始化的时候就将其绑定,以免忘记
		self.server_port = int(input("输入服务器的端口号: "))
		self.tcp_socket.bind(("", self.server_port))
		print("-----------结束初始化--------")

	def listen_socket(self):
		print("---设置为监听状态-----")
		self.tcp_socket.listen(128)  # 最大连接个数
		print("-------设置完成------")

	def accept_client(self):
		# 等待客户端的连接,如果有链接、监听套接字就会产生一个新的套接字为这个客户端一对一服务
		print("--------等待一个客户端的到来-----------")
		self.client_socket, self.client_add = self.tcp_socket.accept()
		print("--------一个新的客户端来了-------------")

	def recv_mes(self):
		print("-----------等待接收消息-------------")
		# 接收客户端发送的消息
		rec_data = self.client_socket.recv(1024)

		# 如果客户端主动调用close()这里也会解堵塞。所以判断接收消息的长度
		if rec_data:
			print("接收到的客户端的消息是: ", rec_data.decode("gbk"))
		else:
			print("没有接收到消息,客户端调用了close")
			self.client_socket.close()
			self.judge = True


	def send_mes(self):
		print("-----------准备发送消息----------")
		send_data = input("输入要发送的信息: ")
		self.client_socket.send(send_data.encode("gbk"))
		print("----------成功发送消息----------")


	def close_socket_servet(self):
		self.tcp_socket.close()

def main():
	# 创建对象
	tcp_server = TcpServer()

	# 监听状态
	tcp_server.listen_socket()
	while True:
	# 等待客户端的连接
		flag = input("请输入是否需要等待客户端的到来:yes表示等待,其他不等待:  ")
		if flag == "yes":
			tcp_server.accept_client()

			while True:
				# 做为服务器 当然是客户端发一个请求,我们回一个消息拉。
				# 接收消息,没有接收到消息会关闭当前套接字
				tcp_server.recv_mes()

				# 发送消息
				tcp_server.send_mes()

			

				if tcp_server.judge:
					break



		#此时当前的套接字已经关闭,如果还需为这个客户端服务,只能重新连接
		else:
			# 如果不需要等待其他客户端的连接,就可以关闭监听套接字
			tcp_server.tcp_socket.close()
			print("程序结束")
			break

    
if __name__ == "__main__":
	main()
	

猜你喜欢

转载自blog.csdn.net/lily559/article/details/82155128