021——搭建TCP网络通信环境(c服务器python客户端)

news2024/11/25 20:48:46

目录

前言

服务器程序

服务器程序验证过程

客户端程序


前言

        驱动开发暂时告一段落了。后面在研究一下OLED和GPS的驱动开发,并且优化前面已经移植过来的这些驱动,我的理念是在封装个逻辑处理层来处理这些驱动程序。server直接操作逻辑处理层的程序。

        这次服务器的开发也不会一步到位,先做最简单的然后在逐渐迭代。

服务器程序

/*  
 * 文件名: server.c  
 * 作者: 辛天宇  
 * 更新时间: 2024-04-10  
 * 软件版本号: 0.0.0  
 */
/**************************************************************
***************************INCLUDE*****************************
**************************************************************/
#include "net.h"
/**************************************************************
****************************LOCAL******************************
**************************************************************/
void cli_data_handle (void *arg);
int main()
{
	int fd = -1;
	struct sockaddr_in sin;
	//创建socket fd*
	if((fd = socket(AF_INET,SOCK_STREAM, 0)) < 0){
		perror("socket");
		//return -1;
		exit(1);
	}
	/*优化4: 允许绑定地址快速重用 */
	int b_reuse = 1;
	setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));
	//绑定
	//填充struct socketddr_in结构体变量
	bzero(&sin,sizeof(sin));//把sin全填充0
	sin.sin_family = AF_INET;//地址族网际网区域
	sin.sin_port = htons(SERV_PORT); //网络字节端口号
	//优化使server可以绑定在任意IP上
#if 1
	sin.sin_addr.s_addr = htonl(INADDR_ANY);//INADDY_ANY = -1
#else
	if( inet_pton(AF_INET,SERV_IP_ADDR,(void *)&sin.sin_addr) != 1){
		perror("inet_pton");
		exit(1);		
	}
#endif
	//绑定
	if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
		perror("bind");
		exit(1);
	}
	//调用listen()把主动套接字变成被动套接字
	if(listen(fd,BACKLOG) < 0 ){
		perror("listen");
		exit(1);
	}
	printf("Server starting...OK!\n");
	int newfd = -1;
	//阻塞等待客户端连接
#if 0
	newfd = accept(fd, NULL, NULL);
	if(newfd < 0){
		perror("accept");
		exit(1);
	}
#else
//通过程序获取刚建立连接的socket客户端的ip地址和端口号
	pthread_t tid;
 
	struct sockaddr_in cin;
	socklen_t addrlen = sizeof (cin);
 
	while (1) {
		if ((newfd = accept (fd, (struct sockaddr *) &cin, &addrlen)) < 0) {
			perror ("accept");
			exit (1);
		}
 
		char ipv4_addr[16];
		if (!inet_ntop (AF_INET, (void *) &cin.sin_addr, ipv4_addr, sizeof (cin))) {
			perror ("inet_ntop");
			exit (1);
		}
 
		printf ("Clinet(%s:%d) is connected!\n", ipv4_addr, htons (cin.sin_port));
 
		pthread_create (&tid, NULL, (void *) cli_data_handle, (void *) &newfd);
	}
 
	close (fd);
	return 0;
}
#endif
void cli_data_handle (void *arg)
{
	int newfd = *(int *) arg;
 
	printf ("handler thread: newfd =%d\n", newfd);
 
	//..和newfd进行数据读写
	int ret = -1;
	char buf[BUFSIZ];
	while (1) {
		bzero (buf, BUFSIZ);
		do {
			ret = read (newfd, buf, BUFSIZ - 1);
		} while (ret < 0 && EINTR == errno);
		if (ret < 0) {
 
			perror ("read");
			exit (1);
		}
		if (!ret) {				//对方已经关闭
			break;
		}
		printf ("Receive data: %s\n", buf);
 
		if (!strncasecmp (buf, QUIT_STR, strlen (QUIT_STR))) {	//用户输入了quit字符
			printf ("Client(fd=%d) is exiting!\n", newfd);
			break;
		}
	}
	close (newfd);
 
}
 
 
 
 
 

这是以前学网络编程的时候写的拿过来改一改

稍微改一下

/*
*author   : xintianyu
*function : main
*data     : 2024-4-10
-----------------------
*author : ???
*return : ???
*data   : ???
*/
int main(int argc, char *argv[])
{
	if(ERROR == usage(argc, argv))
        return 0;
    tcp_server(argc, argv);
    return 0;
}
/*
*author : xintianyu
*return : err num
*data   : 2024-4-10
-----------------------
*author : ???
*return : ???
*data   : ???
*/
int usage(int argc, char *argv[])
{ 
    if (argc != 3)
    {  
        printf("Usage: %s <ip_address> <port>\n", argv[0]);  
        return ERROR;  
    }
    else
    {
        return NOERROR;
    }
}
/*
*author : xintianyu
*return : err num
*data   : 2024-4-10
-----------------------
*author : ???
*return : ???
*data   : ???
*/
int tcp_server(int argc, char *argv[]) 
{
    int server_fd, client_fd;  
    struct sockaddr_in server_addr, client_addr;  
    socklen_t client_len = sizeof(client_addr);  
    char buffer[BUFFER_SIZE];  
    char *ip_address = argv[1];  
    int port = atoi(argv[2]);  
  
    // 创建TCP套接字  
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
        perror("socket creation failed");  
        exit(EXIT_FAILURE);  
    }  
  
    // 设置服务器地址信息  
    memset(&server_addr, 0, sizeof(server_addr));  
    server_addr.sin_family = AF_INET;  
    server_addr.sin_addr.s_addr = inet_addr(ip_address);  
    server_addr.sin_port = htons(port);  
  
    // 绑定套接字到服务器地址  
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {  
        perror("bind failed");  
        exit(EXIT_FAILURE);  
    }  
  
    // 监听套接字  
    if (listen(server_fd, 5) < 0) {  
        perror("listen failed");  
        exit(EXIT_FAILURE);  
    }  
  
    printf("Server listening on %s:%d...\n", ip_address, port);  
  
    while (1) {  
        // 接受客户端连接  
        if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) < 0) {  
            perror("accept failed");  
            continue;  
        }  
  
        // 打印客户端信息  
        char client_ip[INET_ADDRSTRLEN];  
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);  
        printf("Client connected from %s:%d\n", client_ip, ntohs(client_addr.sin_port));  
  
        // 接收客户端消息  
        memset(buffer, 0, BUFFER_SIZE);  
        ssize_t bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);  
        if (bytes_read < 0) {  
            perror("recv failed");  
            close(client_fd);  
            continue;  
        }  
  
        // 确保消息以换行符结尾,并打印接收到的消息  
        if (bytes_read > 0 && buffer[bytes_read - 1] != '\n') {  
            buffer[bytes_read] = '\n';  
            buffer[bytes_read + 1] = '\0';  
        }  
        printf("Received message: %s", buffer);  
  
        // 回复客户端消息  
        strcpy(buffer, "Hello, client!\n");  
        if (send(client_fd, buffer, strlen(buffer), 0) < 0) {  
            perror("send failed");  
        }  
  
        close(client_fd);  
    }
    close(server_fd);
    return NOERROR;  
}

写的比较简单因为没有业务逻辑暂时只是验证通信问题。

服务器程序验证过程

编译命令

这是我们现在的目录结构

客户端程序

import socket

server_ip   = '192.168.5.110'
server_port = 8888 

# 设置服务器地址和端口  
server_address = (server_ip, server_port)
# 创建一个socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接到服务器  
client_socket.connect(server_address)  
try:  
    # 发送数据  
    message = 'Hello, server!'.encode()  
    print(f'Sending {message}')  
    client_socket.sendall(message)  
  
    # 接收数据  
    amount_received = 0  
    amount_expected = len(message)  
  
    while amount_received < amount_expected:  
        data = client_socket.recv(16)  
        amount_received += len(data)  
        print(f'Received {data}')  
  
finally:  
    # 关闭连接  
    print('Closing socket')  
    client_socket.close()

一下就没了我优化一下让他可以一直通信

import socket  
  
server_ip   = '192.168.5.110'
server_port = 8888 

# 设置服务器地址和端口  
server_address = (server_ip, server_port)
  
# 创建一个socket对象  
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
  
# 连接到服务器  
try:  
    client_socket.connect(server_address)  
    print(f'Connected to {server_address}')  
  
    # 接收用户输入并发送给服务器  
    while True:  
        try:  
            user_input = input('Enter command (or "exit" to quit): ')  
            if user_input.lower() == 'exit':  
                break  
            client_socket.sendall(user_input.encode())  
  
            # 接收服务器的响应  
            data = client_socket.recv(1024)  
            print(f'Received: {data.decode()}')  
  
        except KeyboardInterrupt:  
            print('\nKeyboardInterrupt received, exiting...')  
            break  
        except ConnectionResetError:  
            print('\nConnection reset by server, exiting...')  
            break  
        except Exception as e:  
            print(f'An error occurred: {e}, trying to reconnect...')  
            client_socket.close()  # Close the socket if there's an error  
            client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # Create a new one  
            client_socket.connect(server_address)  # Reconnect to the server  
  
finally:  
    # 关闭连接  
    print('Closing socket')  
    client_socket.close()

有问题哇,只能发过去第一条

一顿debug发现是服务器的问题,现在算是通讯正常了。

服务器最新程序

int tcp_server(int argc, char *argv[]) 
{
    int server_fd, client_fd;  
    struct sockaddr_in server_addr, client_addr;  
    socklen_t client_len = sizeof(client_addr);  
    char buffer[BUFFER_SIZE];  
    char *ip_address = argv[1];  
    int port = atoi(argv[2]);  
  
    // 创建TCP套接字  
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
        perror("socket creation failed");  
        exit(EXIT_FAILURE);  
    }  
  
    // 设置服务器地址信息  
    memset(&server_addr, 0, sizeof(server_addr));  
    server_addr.sin_family = AF_INET;  
    server_addr.sin_addr.s_addr = inet_addr(ip_address);  
    server_addr.sin_port = htons(port);  
  
    // 绑定套接字到服务器地址  
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {  
        perror("bind failed");  
        exit(EXIT_FAILURE);  
    }  
  
    // 监听套接字  
    if (listen(server_fd, 5) < 0) {  
        perror("listen failed");  
        exit(EXIT_FAILURE);  
    }  
  
    printf("Server listening on %s:%d...\n", ip_address, port);  
  
    // 接受客户端连接  
    if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) < 0) {  
        perror("accept failed");  
    }
    while (1) 
    {
        // 打印客户端信息  
        char client_ip[INET_ADDRSTRLEN];  
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);  
        printf("Client connected from %s:%d\n", client_ip, ntohs(client_addr.sin_port));  
  
        // 接收客户端消息  
        memset(buffer, 0, BUFFER_SIZE);  
        ssize_t bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);  
        if (bytes_read < 0) {  
            perror("recv failed");  
            close(client_fd);  
            continue;  
        }  
  
        // 确保消息以换行符结尾,并打印接收到的消息  
        if (bytes_read > 0 && buffer[bytes_read - 1] != '\n') {  
            buffer[bytes_read] = '\n';  
            buffer[bytes_read + 1] = '\0';  
        }  
        printf("Received message: %s", buffer);  
  
        // 回复客户端消息  
        strcpy(buffer, "Hello, client!\n");  
        if (send(client_fd, buffer, strlen(buffer), 0) < 0) 
        {  
            perror("send failed");  
        }
    }
    close(client_fd); 
    close(server_fd);
    return NOERROR;  
}

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

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

相关文章

统信UOS(Linux)安装nvm node管理工具

整篇看完再操作&#xff0c;有坑&#xff01;&#xff01; 官网 nvm官网 按照官网方式安装&#xff0c;一直报 错 经过不断研究&#xff0c;正确步骤如下 1、下载安装包 可能因为网络安全不能访问github&#xff0c;我是链接热点下载的 wget https://github.com/nvm-sh/…

基于springboot+vue+Mysql的职称评审管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

Mac安装配置ElasticSearch和Kibana 8.13.2

系统环境&#xff1a;Mac M1 (MacOS Sonoma 14.3.1) 一、准备 从Elasticsearch&#xff1a;官方分布式搜索和分析引擎 | Elastic上下载ElasticSearch和Kibana 笔者下载的是 elasticsearch-8.13.2-darwin-aarch64.tar.gz kibana-8.13.2-darwin-aarch64.tar.gz 并放置到个人…

序列化、反序列化:将对象以字节流的方式,进行写入或读取

序列化&#xff1a;将指定对象&#xff0c;以"字节流"的方式写入一个文件或网络中。 反序列化&#xff1a;从一个文件或网络中&#xff0c;以"字节流"的方式读取到对象。 package com.ztt.Demo01;import java.io.FileNotFoundException; import java.io.Fi…

C++的stack和queue类(一):适配器模式、双端队列与优先级队列

目录 基本概念 适配器模式 stack.h test.cpp 双端队列-deque 仿函数 优先级队列 基本概念 1、stack和queue不是容器是容器适配器&#xff0c;它们没有迭代器 2、stack的quque的默认容器是deque&#xff0c;因为&#xff1a; stack和queue不需要遍历&#xff0…

基于SSM+Jsp+Mysql的农产品供销服务系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

0基础想进入IT行业,可以从这个框架入手

行业现状 IT、AI都是很多年来的热门话题&#xff0c;以至于时至今日&#xff0c;哪怕IT行业已经卷成狗&#xff0c;依然有无数的人想要挤进这个行业。 大模型、云原生、react等等&#xff0c;无数的技术、概念应运而生。那么作为一个没有基础的人&#xff0c;该如何进入这个行…

第十四届蓝桥杯模拟考试II_物联网设计

还是要稳妥啊&#xff0c;写A板的时候感觉很简单所以将模块都混在一起了&#xff0c;结果不出意外就出BUG了又得从头开始查BUG,多简单的题模块最好都分块写写完就检查&#xff0c;这样一步一个脚印多稳 这个模块出了俩BUG第一个是要检查有没有数据进入if语句&#xff0c;不然标…

Kubernetes(k8s)监控与报警(qq邮箱+钉钉):Prometheus + Grafana + Alertmanager(超详细)

Kubernetes&#xff08;k8s&#xff09;监控与报警&#xff08;qq邮箱钉钉&#xff09;&#xff1a;Prometheus Grafana Alertmanager&#xff08;超详细&#xff09; 1、部署环境2、基本概念简介2.1、Prometheus简介2.2、Grafana简介2.3、Alertmanager简介2.4、Prometheus …

OpenCV | 图像读取与显示

OpenCV 对图像进行处理时&#xff0c;常用API如下&#xff1a; API描述cv.imread根据给定的磁盘路径加载对应的图像&#xff0c;默认使用BGR方式加载cv.imshow展示图像cv.imwrite将图像保存到磁盘中cv.waitKey暂停一段时间&#xff0c;接受键盘输出后&#xff0c;继续执行程序…

力扣面试150 分发糖果 分步贪心

Problem: 135. 分发糖果 思路 &#x1f468;‍&#x1f3eb; 参考&#xff1a;代码随想录 一次是从左到右遍历&#xff0c;只比较右边孩子评分比左边大的情况。一次是从右到左遍历&#xff0c;只比较左边孩子评分比右边大的情况。 复杂度 时间复杂度: O ( n ) O(n) O(n) …

代码随想录算法训练营第三十六天| LeetCode 435. 无重叠区间、763.划分字母区间、56. 合并区间

一、LeetCode 435. 无重叠区间 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0435.%E6%97%A0%E9%87%8D%E5%8F%A0%E5%8C%BA%E9%97%B4.html 状态&#xff1a;已解决 1.思路 本题的局部最优是尽量移除与某个区间重叠的其他区间&#xff0c;全局最优是移除的…

构建强健身体的未来:健身管理平台微服务架构解析

在现代社会&#xff0c;人们越来越关注健康和身体素质的提升。健身管理平台应运而生&#xff0c;为用户提供个性化的健身计划、监测和管理工具。微服务架构作为一种灵活且可扩展的系统设计方法&#xff0c;为健身管理平台提供了高效、可靠的基础。 1. 概述健身管理平台微服务架…

Open CASCADE学习|统计形状拓扑数量

边界表示法&#xff08;Boundary Representation&#xff0c;简称B-Rep&#xff09;是几何造型中最成熟、无二义的表示法。它主要用于描述物体的几何信息和拓扑信息。在边界表示法中&#xff0c;一个实体&#xff08;Solid&#xff09;由一组封闭的面&#xff08;Face&#xff…

创建大量栅格文件并分别写入像元数据:C++ GDAL代码实现

本文介绍基于C语言GDAL库&#xff0c;批量创建大量栅格遥感影像文件&#xff0c;并将数据批量写入其中的方法。 首先&#xff0c;我们来明确一下本文所需实现的需求。已知我们对大量遥感影像进行了批量读取与数据处理操作——具体过程可以参考文章C GDAL提取多时相遥感影像中像…

nginx工作原理解析

目录 1、master-workers 的工作机制介绍 2、master-workers 的机制的好处 3、设置多少个 worker 4、最大连接数和支持的最大并发数的计算 1、master-workers 的工作机制介绍 nginx在启动后&#xff0c;会有一个master进程和一个或者多个相互独立的worker进程 过来的请求由…

HDLbits 刷题 --Exams/m2014 q4h

Implement the following circuit: 实现以下电路&#xff1a; module top_module (input in,output out);assign out in; endmodule 运行结果&#xff1a;

Spark_SparkSql写入Oracle_Undefined function.....将长字符串写入Oracle中方法..

在使用Spark编写代码将读库处理然后写入Oracle中遇到了诸多小bug,很磨人。shit!! 实测1&#xff1a;TO_CLOB(a3) 代码样例 --这是一个sparksql写入hive的一个小逻辑&#xff0c;我脱敏了噻 SELECT a1, a2, TO_CLOB(a3) AS clob_data, TO_DATE(a4) AS time FROM table1 WHERE…

关于Linux下的进程等待(进程篇)

目录 为什么存在进程等待&#xff1f;进程等待是在做什么&#xff1f; 怎样去执行进程等待&#xff1f; status options 为什么存在进程等待&#xff1f;进程等待是在做什么&#xff1f; 代码示例&#xff1a;模仿僵尸进程 #include <stdio.h> #include <unistd.…

3D-Aware Multi-Class Image-to-Image Translation with NeRFs

3D-Aware Multi-Class Image-to-Image Translation with NeRFs 利用NeRFs实现3D感知的多类图像到图像的翻译 Senmao Li1  Joost van de Weijer2  Yaxing Wang1 李森茂 1 范德维杰 2 王亚兴 1  Fahad Shahbaz Khan3,4  Meiqin Liu5  Jian Yang1 法哈德夏巴兹汗 3,4 刘梅琴 …