TCP服务器与客户端搭建

一、思维导图

二、给代码添加链表

        【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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JVM春招快速学习指南

1.说在前面 在Java相关岗位的春/秋招面试过程中&#xff0c;JVM的学习是必不可少的。本文主要是通过《深入理解Java虚拟机》第三版来介绍JVM的学习路线和方法&#xff0c;并对没有过JVM基础的给出阅读和学习建议&#xff0c;尽可能更加快速高效的进行JVM的学习与秋招面试的备战…

kafka服务端之副本

文章目录 概述副本剖析失效副本ISR的伸缩LWLEO与HW的关联LeaderEpoch的介入数据丢失的问题数据不一致问题Leader Epoch数据丢失数据不一致 kafka为何不支持读写分离 日志同步机制可靠性分析 概述 Kafka中采用了多副本的机制&#xff0c;这是大多数分布式系统中惯用的手法&…

aarch64 Ubuntu20.04 安装docker

安装 docker 依赖项&#xff1a;sudo apt-get update sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release添加 Docker GPG 密钥&#xff1a;curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyr…

校园网规划方案

个人博客站—运维鹿: http://www.kervin24.top CSDN博客—做个超努力的小奚&#xff1a; https://blog.csdn.net/qq_52914969?typeblog 本课程设计参考学习计算机网络 思科Cisco Packet Tracer仿真实验_哔哩哔哩_bilibili, 文章和pkg详见个人博客站: http://www.kervin24.to…

语义分割文献阅读——SETR:使用Transformer从序列到序列的角度重新思考语义分割

目录 摘要 Abstract 1 引言 2 Vision Transformer(ViT) 2.1 图片预处理&#xff1a;分块和降维 2.2 Patch Embedding 2.3 位置编码 2.4 Transformer Encoder的前向过程 3 SETR 3.1 图像序列化处理 3.2 Transformer 3.3 解码器 总结 摘要 本周阅读的论文题目是《R…

Mac上搭建k8s环境——Minikube

1、在mac上安装Minikube可执行程序 brew cask install minikub 安装后使用minikube version命令查看版本 2、安装docker环境 brew install --cask --appdir/Applications docker #安装docker open -a Docker #启动docker 3、安装kubectl curl -LO https://storage.g…

5. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--Nacos

一、什么是Nacos Nacos 是阿里巴巴开源的一款云原生应用基础设施&#xff0c;它旨在简化微服务架构中服务治理和配置管理的复杂性。通过 Nacos&#xff0c;服务在启动时可以自动注册&#xff0c;而其他服务则可以通过名称来查找并访问这些注册好的实例。同时&#xff0c;Nacos…

【后端开发】系统设计101——Devops,Git与CICD,云服务与云原生,Linux,安全性,案例研究(30张图详解)

【后端开发】系统设计101——Devops&#xff0c;Git与CICD&#xff0c;云服务与云原生&#xff0c;Linux&#xff0c;安全性&#xff0c;案例研究&#xff08;30张图详解&#xff09; 文章目录 1、DevopsDevOps与SRE与平台工程的区别是什么&#xff1f;什么是k8s&#xff08;Ku…

100天精通Python(爬虫篇)——第113天:爬虫基础模块之urllib详细教程大全

文章目录 1. urllib概述2. urllib.request模块 1. urllib.request.urlopen()2. urllib.request.urlretrieve()3. urllib.request.Request()4. urllib.request.install_opener()5. urllib.request.build_opener()6. urllib.request.AbstractBasicAuthHandler7. urllib.request.…

win32汇编环境,结构体的使用示例一

;运行效果 ;win32汇编环境,结构体的使用示例一 ;举例说明结构体的定义&#xff0c;如何访问其中的成员&#xff0c;使用assume指令指向某个结构体&#xff0c;利用偏移得到成员值等 ;直接抄进RadAsm可编译运行。重要部分加备注。 ;下面为asm文件 ;>>>>>>>…

opencv:基于暗通道先验(DCP)的内窥镜图像去雾

目录 项目大体情况 暗通道先验&#xff08;Dark Channel Prior, DCP&#xff09;原理 项目代码解析 该项目是由我和我导师与舟山某医院合作开发的一个基于暗通道先验&#xff08;Dark Channel Prior&#xff0c;DCP&#xff09;的内窥镜图像去雾方法。具体来说&#xff0c;…

Java 大视界 -- Java 大数据在智能政务中的应用与服务创新(78)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【DeepSeek】DeepSeek概述 | 本地部署deepseek

目录 1 -> 概述 1.1 -> 技术特点 1.2 -> 模型发布 1.3 -> 应用领域 1.4 -> 优势与影响 2 -> 本地部署 2.1 -> 安装ollama 2.2 -> 部署deepseek-r1模型 1 -> 概述 DeepSeek是由中国的深度求索公司开发的一系列人工智能模型&#xff0c;以其…

数据库,数据表的增删改查操作

一.数据库的基本操作 &#xff08;1&#xff09;创建数据库 创建数据库就是在数据库系统中划分一块存储数据的空间&#xff0c;方便数据的分配、放置和管理。在MySQL中使用CREATE DATABASE命令创建数据库&#xff0c;语法格式如下: CREATE DATABASE数据库名称; 注&#xff1a…

书籍《新能源汽车动力电池安全管理算法设计》和《动力电池管理系统核心算法》脑图笔记

目录 一、阅读背景二、《新能源汽车动力电池安全管理算法设计》脑图笔记三、《动力电池管理系统核心算法》脑图笔记四、后记参考学习 一、阅读背景 如今身处新能源动力电池行业&#xff0c;欲对动力电池相关算法做一些了解&#xff0c;通过查找相关电子书app&#xff0c;最后找…

激活函数篇 03 —— ReLU、LeakyReLU、RandomizedLeakkyReLU、PReLU、ELU

本篇文章收录于专栏【机器学习】 以下是激活函数系列的相关的所有内容: 一文搞懂激活函数在神经网络中的关键作用 逻辑回归&#xff1a;Sigmoid函数在分类问题中的应用 整流线性单位函数&#xff08;Rectified Linear Unit, ReLU&#xff09;&#xff0c;又称修正线性单元&a…

Python Pandas(3):DataFrame

1 介绍 DataFrame 是 Pandas 中的另一个核心数据结构&#xff0c;类似于一个二维的表格或数据库中的数据表。它含有一组有序的列&#xff0c;每列可以是不同的值类型&#xff08;数值、字符串、布尔型值&#xff09;。DataFrame 既有行索引也有列索引&#xff0c;它可以被看做由…

【C++高并发服务器WebServer】-14:Select详解及实现

本文目录 一、BIO模型二、非阻塞NIO忙轮询三、IO多路复用四、Select()多路复用实现 明确一下IO多路复用的概念&#xff1a;IO多路复用能够使得程序同时监听多个文件描述符&#xff08;文件描述符fd对应的是内核读写缓冲区&#xff09;&#xff0c;能够提升程序的性能。 Linux下…

算法兵法全略(译文)

目录 始计篇 谋攻篇 军形篇 兵势篇 虚实篇 军争篇 九变篇 行军篇 地形篇 九地篇 火攻篇 用间篇 始计篇 算法&#xff0c;在当今时代&#xff0c;犹如国家关键的战略武器&#xff0c;也是处理各类事务的核心枢纽。算法的世界神秘且变化万千&#xff0c;不够贤能聪慧…

瑞芯微 Rockchip 系列 RK3588 主流深度学习框架模型转成 rknn 模型教程

前言 在瑞芯微 Rockchip 芯片上进行 NPU 推理&#xff0c;需要先将模型文件转换成 rknn 模型文件&#xff0c;才能执行各种推理任务。本文将介绍如何安装各种工具&#xff0c;并最终实现将各种深度学习框架的模型文件转换成 rknn 文件。 本教程不仅适合 RK3588 平台&#xff…