客户端通过服务器进行TCP通信(三)

一. 对TCP的基础讲解

服务端

1. 首先创建一个套接字,TCP是面向字节流的套接字,故需要使用SOCK_STREAM

2. 然后使用bind()函数将套接字与服务器地址关联(如果是在本地测试,直接将地址设置为217.0.0.1或者localhost,端口号为10000)

3. listen()将套接字设置为监听状态

3. 等待,参数为最大排队数

4. 在循环中,调用accept()等待客户端的消息连接,如果有客户端进行连接,那么accept()函数会返回一个打开的连接与客户端地址

6. 指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据

7. 通过sendall()进行回传客户端数据

8. 传回数据后,与当前的客户端通信就算完成了。需要使用close()进行关闭清理

客户端

1. 创建一个套接字

2. 使用connect()函数连接到服务器

3. 通过sendall()向服务器发送数据

4. 通过recv()接受服务器传递回的数据

5. 交互完成之后,使用close()关闭清理

二. 编写Python程序

2.1 Python实现一个服务端和一个客户端连接

服务端代码

# coding=gb2312
import socketsocket_server = socket.socket()
socket_server.bind(("localhost", 8888))
# 监听端口
socket_server.listen(1)
# 等待客户端连接,accept方法返回二元元组(连接对象, 客户端地址信息)
print(f"服务端已开始监听,正在等待客户端连接...")
conn, address = socket_server.accept()
print(f"接收到了客户端的连接,客户端的信息:{address}")# 接受客户端信息,使用客户端和服务端的本次连接对象,而非socket_server
while True:# 接收消息data: str = conn.recv(1024).decode("UTF-8")print(f"客户端发来的消息是:{data}")# 回复消息msg = input("请输入你要回复客户端的消息:")if msg == 'exit':breakconn.send(msg.encode("UTF-8"))  # encode将字符串编码为字节数组对象# 关闭连接
conn.close()
socket_server.close()

客户端代码

# coding=gb2312
import socket
# 创建socket对象
socket_client = socket.socket()
# 连接到服务器
socket_client.connect(("localhost", 8888))while True:send_msg = input("请输入要发送给服务端的消息:")if send_msg == "exit":break# 发送消息socket_client.send(send_msg.encode("UTF-8"))# 接受消息recv_data = socket_client.recv(1024).decode("UTF-8")    # 1024是缓冲区大小,一般就填1024, recv是阻塞式print(f"服务端回复的消息是:{recv_data}")# 关闭连接
socket_client.close()

运行之后我们就实现了客户端和服务端的通信,但此时只能有一个客户端连接到服务端,如果想实现多个客户端,就需要修改服务端listen()的参数,允许更多的客户端连接,下面进行讲解。

2.2 Python实现一个服务端和多个客户端连接

服务端代码

# coding=gb2312
import socket
import threadingdef create_server_socket(host, port):socket_server = socket.socket()socket_server.bind((host, port))socket_server.listen(5)print(f"服务端已启动,地址{host},端口{port}")print(f"正在等待客户端连接...")# 开启多线程,收发来自多个客户端的数据num = 0     # 标记客户端的编号while True:num += 1conn, address = socket_server.accept()print(f"服务端已接受到客户端 {num}号 的连接请求,客户端信息:{address}")client_handler = threading.Thread(target=handle_client, args=(conn, address, num))client_handler.start()# 处理收发数据
def handle_client(conn, address, num):while True:# 接收客户端发来的数据data_from_client: str = conn.recv(1024).decode("UTF-8")print(f"客户端 {num}号:{address}发来的消息是:{data_from_client}")# 发送消息到客户端msg = input(f"请输入你要回复客户端 {num}号:{address}的消息:")if msg == 'exit':breakconn.send(msg.encode("UTF-8"))  # encode将字符串编码为字节数组对象conn.close()if __name__ == '__main__':server_host = input("请输入服务端Host:")server_port = int(input("请输入服务端port:"))create_server_socket(server_host, server_port)

客户端代码

# coding=gb2312
import socketdef create_client(host, port):socket_client = socket.socket()socket_client.connect((host, port))# 发送、接受数据while True:msg = input(f"请输入客户端1发送给服务端{host}:{port}的数据:")if msg == "exit":break# 发送数据到服务端socket_client.send(msg.encode("UTF-8"))# 接收服务端的数据data_from_server = socket_client.recv(1024).decode("UTF-8")print(f"客户端接收到服务端的消息:{data_from_server}")socket_client.close()if __name__ == '__main__':server_host = input("请输入想要连接的服务端Host:")server_port = int(input("请输入想要连接的服务端port:"))create_client(server_host, server_port)

三. 移植Python程序

注意,服务器上的python版本和vscode上使用的服务器版本一定要一致。因为上述代码都是在Python3下写的,且我服务器的的python版本是python2,所以下面对代码进行一定的更改。

# coding=gb2312
# -*- coding: utf-8 -*-
# import os
# os.environ["CUDA_VISIBLE_DEVICES"] = "0, 1"
from __future__ import print_function
import socket
import threadingdef create_server_socket():socket_server = socket.socket()socket_server.bind(("localhost",50000))# socket_server.bind(("47.116.118.86",5000))socket_server.listen(65000)print("正在等待客户端连接...")# 开启多线程,收发来自多个客户端的数据num = 0     # 标记客户端的编号while True:num += 1conn, address = socket_server.accept()print("服务端已接受到客户端 {}号 的连接请求,客户端信息:{}".format(num,address))client_handler = threading.Thread(target=handle_client, args=(conn, address, num))client_handler.start()# 处理收发数据
def handle_client(conn, address, num):while True:# 接收客户端发来的数据data_from_client = conn.recv(1024).decode("UTF-8")print("客户端 {}号:{}发来的消息是:{}".format(num,address,data_from_client))# 发送消息到客户端#msg = raw_input("请输入你要回复客户端 {}号:{}的消息:".format(num,address))msg = data_from_clientif msg == 'exit':breakconn.send(msg.encode("UTF-8"))  # encode将字符串编码为字节数组对象conn.close()if __name__ == '__main__':create_server_socket();# create_server_socket("172.19.84.229", 8080)# create_server_socket("", 8080)

3.2 在服务器运行Python程序

在py文件中加入以下代码:

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0, 1"

添加后,在服务器直接运行python xxxx.py,就可以运行这个Python文件了。

四. 实现服务端运行python服务端程序,与客户端通信

在阿里云服务器监听服务器的内网IP,例如172.22.71.222,端口号设置为8080.

在客户端去连接的不是服务器的内网IP,而是云服务器的公网IP,如47.112.113.43,端口号也设置为8080

这样便能连接成功

这样我们就可以在云服务器作为服务端,在自己本机作为客户端,实现TCP传输。

如果我们要实现客户端到客户端的通信的话,可以在服务端开辟多个线程,去处理客户端的数据。

此时主线程负责对发起请求的客户创建链接,并且将每个用户对应的链接保存到一个字典中去,方便调用。对于每个用户链接,都创建两个子线程,一个子线程用来发送数据,另外一个子线程用来接收数据。

但这种方法如果客户端多的话,就对资源消耗很大,因此这个项目我就摒弃了这个方法,从而采用直接从数据库中获取数据,实现多个客户端去获取云服务器的MYSQL数据库的数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/46585.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内存函数(C语言)

内存函数 以下函数的头文件:string.h 针对内存块进行处理的函数 memcpy 函数原型: void* memcpy(void* destination, const void* source, size_t num);目标空间地址 源空间地址num,被拷贝的字节个数 返回目标空间的起始地…

Python与自动化脚本编写

Python与自动化脚本编写 Python因其简洁的语法和强大的库支持,成为了自动化脚本编写的首选语言之一。在这篇文章中,我们将探索如何使用Python来编写自动化脚本,以简化日常任务。 一、Python自动化脚本的基础 1. Python在自动化中的优势 Pyth…

1.31、基于长短记忆网络(LSTM)的发动机剩余寿命预测(matlab)

1、基于长短记忆网络(LSTM)的发动机剩余寿命预测的原理及流程 基于长短期记忆网络(LSTM)的发动机剩余寿命预测是一种常见的机器学习应用,用于分析和预测发动机或其他设备的剩余可用寿命。下面是LSTM用于发动机剩余寿命预测的原理和流程: 数据收集&#…

【Linux】 GCC/G++与Makefile使用

Linux GCC/G使用 GCC如何完成 格式:gcc [选项] 要编译的文件 [选项] [目标文件] 常用选项: -E:让gcc在预处理结束后停止编译过程,输出.i的C语言原始文件。-S:该选项只是进行编译而不是进行汇编,最终生成汇…

力扣144题:二叉树的先序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3]示例 2: 输入:root [] 输出:[]示例 3: 输入:root [1] 输出&am…

C++入门学习——初始化列表

概念 初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括 号中的初始值或表达式 class Date { public://初始化列表Date(int year,int month,int day):_year(year),_month(month),_d…

[Windows] 油.管视频下载神器 Gihosoft TubeGet Pro v9.3.88

描述 对于经常在互联网上进行操作的学生,白领等! 一款好用的软件总是能得心应手,事半功倍。 今天给大家带了一款高科技软件 管视频下载神器 无需额外付费,永久免费! 亲测可运行!! 内容 目前主…

高德地图显示圆形区域并在区域边上标注半径

bug:循环创建三个圆形区域 ,数组设置为[{raduis:500,color:“#FF0000”}],然后循环取颜色会莫名其妙报错修改为 strokeColor: [“#FF0000”, “#1EE3C2”, “#3772E9”][i]即可 initAMap() {AMapLoader.load({key: "130cca3be68a2ff0fd5…

记VMware网络适配器里的自定义特定虚拟网络一直加载问题解决办法

1、问题描述 VMware网络适配器里的自定义特定虚拟网络一直加载问题: 在自定义:特定虚拟网络选择的时候 没有上图所示的三个选择,而是正在加载虚拟网络.... 如下图所示: 2、解决办法 2.1、原因分析: 是安装时候出现…

安防视频监控/视频汇聚EasyCVR平台浏览器http可以播放,https不能播放,如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台基于云边端一体化架构,兼容性强、支持多协议接入,包括国标GB/T 28181协议、部标JT808、GA/T 1400协议、RTMP、RTSP/Onvif协议、海康Ehome、海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石云SD…

7.15洛谷蓝题

二分答案的两个模板&#xff1a; 1.最小值的最大化&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include<bits/stdc.h> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<…

Studying-代码随想录训练营day40| 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

第40天&#xff0c;动态规划part07&#xff0c;动态规划经典题型“打家劫舍”(ง •_•)ง&#xff0c;编程语言&#xff1a;C 目录 198.打家劫舍 213.打家劫舍II 337.打家劫舍III 总结 198.打家劫舍 文档讲解&#xff1a;代码随想录打家劫舍 视频讲解&#xff1a;手…

【C++进阶学习】第七弹——AVL树——树形结构存储数据的经典模块

二叉搜索树&#xff1a;【C进阶学习】第五弹——二叉搜索树——二叉树进阶及set和map的铺垫-CSDN博客 目录 一、AVL树的概念 二、AVL树的原理与实现 AVL树的节点 AVL树的插入 AVL树的旋转 AVL树的打印 AVL树的检查 三、实现AVL树的完整代码 四、总结 前言&#xff1a…

JavaScript青少年简明教程:输入输出

JavaScript青少年简明教程&#xff1a;输入输出 JavaScript的输入输出情况相对复杂&#xff0c;因为它依赖于其运行的宿主环境&#xff08;如Web浏览器或Node.js&#xff09;来提供具体的输入输出机制。JavaScript的核心规范&#xff08;ECMAScript&#xff09;本身并不直接提…

C基础day9

一、思维导图 二、课后练习 1> 使用递归实现 求 n 的 k 次方 #include<myhead.h>int Pow(int n,int k) {if(k 0 ) //递归出口{return 1;}else{return n*Pow(n,k-1); //递归主体} }int main(int argc, const char *argv[]) {int n0,k0;printf("请输入n和k:&…

韩国coupang上线的卖家官网是什么?韩国电商有哪些平台?

根据Statista的调查报告&#xff0c;预计2024年电子商务市场收入将达到4.117亿美元。而韩国的电子商务市场是全球最具活力和创新性的市场之一&#xff0c;有数据显示2023年韩国电商市场规模已突破1700亿美元&#xff0c;全球排名第四。 韩国coupang上线的卖家官网是什么&#x…

Linux虚拟机扩展磁盘空间

文章目录 在VM上进行扩展新的磁盘空间进入虚拟机将扩展的磁盘空间分配给对应的分区 VM 下的Linux虚拟机提示磁盘空间不足&#xff0c;需要对其进行磁盘扩容&#xff0c;主要有以下两步&#xff1a; 在VM上进行扩展新的磁盘空间 先关闭虚拟机在VM的虚拟机设置处进行硬盘扩展 …

Redislnsight-v2远程连接redis

redis安装内容添加&#xff1a; Linux 下使用Docker安装redis-CSDN博客 点击添加 添加ip地址&#xff0c;密码&#xff0c;端口号 创建完成 点击查看内容&#xff1a;

Redis的单线程讲解与指令学习

目录 一.Redis的命令 二.数据类型 三.Redis的key的过期策略如何实现&#xff1f; 四.Redis为什么是单线程的 五.String有关的命令 Redis的学习专栏&#xff1a;http://t.csdnimg.cn/a8cvV 一.Redis的命令 两个基本命令 在Redis当中&#xff0c;有两个基本命令&#xff1…

记录些MySQL题集(3)

MySQL 分区技术深入解析 分区的基本概念 MySQL分区 是一种数据库优化的技术&#xff0c;它允许将一个大的表、索引或其子集分割成多个较小的、更易于管理的片段&#xff0c;这些片段称为“分区”。每个分区都可以独立于其他分区进行存储、备份、索引和其他操作。这种技术主要…