TCP服务器与客户端搭建

news2025/2/8 10:03:00

一、思维导图

二、给代码添加链表

        【server.c】

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;

enum Type{
	TYPE_REGIST,
	TYPE_LOGIN
};

typedef struct Pack{
	int size;
	enum Type type;
	char buf[2048];
	int count;
}pack_t;

/*
typedef struct user_info{
	union Data{
		struct user_info* tail;
		char ui[20];
	}data;
	struct user_info* next;
	struct user_info* prev;
}UserInfo;

UserInfo* create_node(){
	UserInfo* node = malloc(sizeof(UserInfo));
	node->next = NULL;
	node->prev = NULL;
	node->data.tail = node;
	return node;
}
*/

//从pack协议包中解析数据
void read_pack(pack_t* pack)
{
	char* buf = pack->buf;
	//记录buf已经读取的字节个数,方便定位到最靠前的未读取的位置
	int readed_size = 0;
	while(1){
		//将buf中最靠前未读取的2个字节,当作short读取,并赋值给data_size
		short data_size = *(short*)(buf + readed_size);
		if(data_size == 0){
			printf("数据解析完毕\n");
			break;
		}
		//因为已经读取了2个字节,readed_size要自增2字节
		readed_size += 2;
		//准备一个大小为data_size+1的字符数组,用来接收数据
		char temp[data_size + 1];
		//初始化该数组
		memset(temp, 0, data_size+1);
		memcpy(temp, buf + readed_size, data_size);
		readed_size += data_size;

		printf("temp = %s\n", temp);
	}
}

int main(int argc, const char* argv[])
{
	if(argc != 2){
		printf("请输入端口号!\n");
		return 1;
	}
	//将字符串转换成int类型port
	int port = atoi(argv[1]);

	//创建服务器套接字
	int server = socket(AF_INET, SOCK_STREAM, 0);

	//准备网络地址结构体: struct sockaddr_in
	addr_in_t addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("0.0.0.0");

	//为套接字绑定ip和port
	if(bind(server, (addr_t*)&addr, sizeof(addr)) == -1){
		perror("bind()");
		return 1;
	}

	//监听
	listen(server, 10);

	//接收客户端的连接
	addr_in_t client_addr = {0};
	int client_addr_len = sizeof(client_addr);
	int client = accept(server, (addr_t*)&client_addr, &client_addr_len);
	if(client != -1){
		printf("=== 客户端连接 ===\n");
	}

	//读取客户端发来的消息
	while(1){
		int pack_size = 0;
		int res = read(client, &pack_size, 4);
		if(res == 0){
			printf("=== 客户端断开连接 === \n");
			return 0;
		}
		//当前的 pack_size = 4(pack.size大小) + 4(pack.type大小) + buf大小
		pack_t pack = {0};
		read(client, (char*)&pack+4, pack_size-4);
		pack.size = pack_size;

		//解析协议包的所有数据
		read_pack(&pack);
	}

	return 0;
}


        【client.c】

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;

enum Type{
	TYPE_REGIST,
	TYPE_LOGIN
};

typedef struct Pack{
	int size; //记录整个协议包实际大小(定长部分,占4个字节)
	enum Type type; //定长部分,占4个字节
	char buf[2048]; //变长部分,占count个字节
	int count; //记录指针偏移量,即buf使用了多少个字节
}pack_t;

/*
typedef struct user_info{
	union Data{
		struct user_info* tail;
		char ui[20];
	}data;
	struct user_info* next;
	struct user_info* prev;
}UserInfo;

UserInfo* create_node(){
	UserInfo* node = malloc(sizeof(UserInfo));
	node->next = NULL;
	node->prev = NULL;
	node->data.tail = node;
	return node;
}
*/

void append(pack_t* pack, const char* data)
{
	char* buf = pack->buf;
	int len = strlen(data);
	//将buf的前2个字节当作short来存储数据len
	*(short*)(buf + pack->count) = len;
	pack->count += 2;

	memcpy(buf + pack->count, data, len);
	pack->count += len;

	pack->size = pack->count + 8;
}

int main(int argc, const char* argv[])
{
	if(argc != 2){
		printf("请输入端口号!\n");
		return 1;
	}
	//将字符串转换成int类型port
	int port = atoi(argv[1]);

	int client = socket(AF_INET, SOCK_STREAM, 0);

	addr_in_t addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("192.168.126.155");

	if(connect(client, (addr_t*)&addr, sizeof(addr)) == -1){
		perror("connect()");
		return 1;
	}

	while(1){
		pack_t pack = {0};
		pack.type=TYPE_LOGIN;
		char name[20] = "";
		char pwd[20] = "";
		printf("请输入账号:");
		scanf("%20s", name);
		while(getchar() != 10);
		
		printf("请输入密码:");
		scanf("%20s", pwd);
		while(getchar() != 10);
		
		//前2个字节记录数据长度n,紧接着的n个字节记录数据本身
		//将name和pwd存入pack.buf中(即将name和pwd按照既定格式添加进协议包))
		append(&pack, name);
		append(&pack, pwd);

		//协议包总共占据 pack.count + 4 字节
		//pack.count 的长度,根据name和pwd的长度动态决定
		write(client, &pack, pack.size);
	}

	return 0;
}

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

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

相关文章

【大数据技术】本机DataGrip远程连接虚拟机MySQL/Hive

本机DataGrip远程连接虚拟机MySQL/Hive datagrip-2024.3.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本机的DataGrip连接虚拟机的MySQL数据库和Hive数据库,提高编程效率。 安装DataGrip 请按照以下步骤安装DataGrip软…

【C++篇】C++11新特性总结1

目录 1&#xff0c;C11的发展历史 2&#xff0c;列表初始化 2.1C98传统的{} 2.2&#xff0c;C11中的{} 2.3&#xff0c;C11中的std::initializer_list 3&#xff0c;右值引用和移动语义 3.1&#xff0c;左值和右值 3.2&#xff0c;左值引用和右值引用 3.3&#xff0c;…

redis之RDB持久化过程

redis的rdb持久化过程 流程图就想表达两点&#xff1a; 1.主进程会fork一个子进程&#xff0c;子进程共享主进程内存数据(fork其实是复制页表)&#xff0c;子进程读取数据并写到新的rdb文件&#xff0c;最后替换旧的rdb文件。 2.在持久化过程中主进程接收到用户写操作&#x…

操作系统—进程与线程

补充知识 PSW程序状态字寄存器PC程序计数器&#xff1a;存放下一条指令的地址IR指令寄存器&#xff1a;存放当前正在执行的指令通用寄存器&#xff1a;存放其他一些必要信息 进程 进程&#xff1a;进程是进程实体的运行过程&#xff0c;是系统进行资源分配和调度的一个独立单位…

CV(11)-图像分割

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 图像分割 语义分割不需要区分具体的个体&#xff0c;实例分割需要 反卷积/转置卷积&#xff1a; 它并不是正向卷积的完全逆过程。反卷积是一种特殊的正向卷积&#xff0c;先按照一定的比例通过补0 来扩大输入图像的尺寸&…

【STM32系列】利用MATLAB配合ARM-DSP库设计FIR数字滤波器(保姆级教程)

ps.源码放在最后面 设计IIR数字滤波器可以看这里&#xff1a;利用MATLAB配合ARM-DSP库设计IIR数字滤波器&#xff08;保姆级教程&#xff09; 前言 本篇文章将介绍如何利用MATLAB与STM32的ARM-DSP库相结合&#xff0c;简明易懂地实现FIR低通滤波器的设计与应用。文章重点不在…

STM32上部署AI的两个实用软件——Nanoedge AI Studio和STM32Cube AI

1 引言 STM32 微控制器在嵌入式领域应用广泛&#xff0c;因为它性能不错、功耗低&#xff0c;还有丰富的外设&#xff0c;像工业控制、智能家居、物联网这些场景都能看到它的身影。与此同时&#xff0c;人工智能技术发展迅速&#xff0c;也逐渐融入各个行业。 把 AI 部署到 STM…

qt+gstreamer快速创建一个流媒体播放器

目录 1 前言 2 playbin3 3 videooverlay 4 关键代码 5 运行示例 1 前言 最近因为工作需求&#xff0c;要实现一个桌面流媒体播放器来支持常见的流媒体协议&#xff0c;经过调研发现使用gstreamer配合一些桌面级的gui应用开发工具如qt可以进行快速实现&#xff0c;在此进…

DeepSeek V2报告阅读

概况 MoE架构&#xff0c;236B参数&#xff0c;每个token激活参数21B&#xff0c;支持128K上下文。采用了包括多头潜在注意力&#xff08;MLA&#xff09;和DeepSeekMoE在内的创新架构。MLA通过将KV缓存显著压缩成潜在向量来保证高效的推理&#xff0c;而DeepSeekMoE通过稀疏计…

零基础Vue入门6——Vue router

本节重点&#xff1a; 路由定义路由跳转 前面几节学习的都是单页面的功能&#xff08;都在专栏里面https://blog.csdn.net/zhanggongzichu/category_12883540.html&#xff09;&#xff0c;涉及到项目研发都是有很多页面的&#xff0c;这里就需要用到路由&#xff08;vue route…

关于JS继承的七种方式和理解

1.原型链继承 function Fun1() {this.name parentthis.play [1, 2, 3] } function Fun2() {this.type child }Fun2.prototype new Fun1()let s1 new Fun2() let s2 new Fun2() s1.play.push(4) console.log(s1.play, s2.play) // [1, 2, 3, 4] [1, 2, 3, 4]可以看到两个…

【Vue】在Vue3中使用Echarts的示例 两种方法

文章目录 方法一template渲染部分js部分方法一实现效果 方法二template部分js or ts部分方法二实现效果 贴个地址~ Apache ECharts官网地址 Apache ECharts示例地址 官网有的时候示例显示不出来&#xff0c;属于正常现象&#xff0c;多进几次就行 开始使用前&#xff0c;记得先…

每日Attention学习18——Grouped Attention Gate

模块出处 [ICLR 25 Submission] [link] UltraLightUNet: Rethinking U-shaped Network with Multi-kernel Lightweight Convolutions for Medical Image Segmentation 模块名称 Grouped Attention Gate (GAG) 模块作用 轻量特征融合 模块结构 模块特点 特征融合前使用Group…

124,【8】buuctf web [极客大挑战 2019] Http

进入靶场 查看源码 点击 与url有关&#xff0c;抓包 over

源路由 | 源路由网桥 / 生成树网桥

注&#xff1a;本文为 “源路由” 相关文章合辑。 未整理去重。 什么是源路由&#xff08;source routing&#xff09;&#xff1f; yzx99 于 2021-02-23 09:45:51 发布 考虑到一个网络节点 A 从路由器 R1 出发&#xff0c;可以经过两台路由器 R2、R3&#xff0c;到达相同的…

FPGA的IP核接口引脚含义-快解

疑问 手册繁琐&#xff0c;怎样快速了解IP核各输入输出接口引脚的含义。 答疑 不慌不慌&#xff0c;手册确实比较详细但繁琐&#xff0c;如何快速知晓该部分信息&#xff0c;涛tao道长给你们说&#xff0c;简单得很&#xff0c;一般新入门的道友有所不知&#xff0c;往往后面…

Qwen2-VL-2B-Instruct 模型 RK3576 板端部署过程

需要先在电脑上运行 RKLLM-Toolkit 工具&#xff0c;将训练好的模型转换为 RKLLM 格式的模型&#xff0c;然后使用 RKLLM C API 在开发板上进行推理。 在安装前先查看板端的内存容量&#xff0c;和自己模型占用大小比较一下&#xff0c;别安装编译好了不能用。 这里我就是先尝试…

如何设计光耦电路

光耦长这样&#xff0c;相信小伙伴们都见过&#xff0c;下图是最为常用的型号PC817 怎么用&#xff1f;我们先看图&#xff0c;如下图1&#xff1a; Vin为输入信号&#xff0c;一般接MCU的GPIO口&#xff0c;由于这里的VCC1为3.3V&#xff0c;故MCU这边的供电电源不能超过3.3V…

ADC模数转换器概念函数及应用

ADC模数转换器概念函数及应用 文章目录 ADC模数转换器概念函数及应用1.ADC简介2.逐次逼近型ADC2.1逐次逼近型ADC2.2stm32逐次逼近型2.3ADC基本结构2.4十六个通道 3.规则组的4种转换模式3.1单次转换&#xff0c;非扫描模式3.2连续转换&#xff0c;非扫描模式3.3单次转换&#xf…

DFX(Design for eXcellence)架构设计全解析:理论、实战、案例与面试指南*

一、什么是 DFX &#xff1f;为什么重要&#xff1f; DFX&#xff08;Design for eXcellence&#xff0c;卓越设计&#xff09;是一种面向产品全生命周期的设计理念&#xff0c;旨在确保产品在设计阶段就具备**良好的制造性&#xff08;DFM&#xff09;、可测试性&#xff08;…