《TCP/IP网络编程》阅读笔记--基于TCP的服务器端/客户端

目录

1--TCP/IP协议栈

2--TCP服务器端默认函数调用顺序

3--TCP客户端的默认函数调用顺序

4--Linux实现迭代回声服务器端/客户端

5--Windows实现迭代回声服务器端/客户端

6--TCP原理

7--Windows实现计算器服务器端/客户端


1--TCP/IP协议栈

        TCP/IP协议栈共分 4 层,可以理解为数据收发分成了 4 个层次化过程;

链路层:

        链路层是物理链接领域标准化的结果,专门定义LAN、WAN、MAN等网络标准;

IP层:

        IP层用于解决数据传输过程中路径的选择问题;

TCP/IP层:

        即传输层,用于解决数据传输的问题(数据顺序、可靠性等);

应用层:

        程序员根据数据传输规则,编写规定的程序(例如Socket)来实现数据传输;

2--TCP服务器端默认函数调用顺序

        一般 TCP 服务器端调用默认函数的顺序如下:socket() 创建 Socket → bind() 分配Socket 地址 → listen() 等待连接请求状态 → accept() 允许连接 → read()/write() 数据交换 → close() 断开连接;

        调用 listen() 函数进入等待连接请求状态,只有服务器端调用了 listen() 函数,客户端才能进入可发出连接请求的状态;

#include <sys/socket.h>int listen(int sock, int backlog); // 成功时返回 0, 失败时返回 -1;// sock 表示希望进入等待连接请求状态的Socket的文件描述符
// backlog 表示连接请求等待队列的长度,即最多可以使多少个连接请求进入队列

        服务器端调用 accept() 函数来受理客户端的连接请求,即受理等待队列中待处理的客户端连接请求;

#include <sys/socket.h>int accept(int sock, struct sockaddr* addr, socklen_t* addrlen);
// 成功时返回创建的Socket的文件描述符,失败时返回-1

3--TCP客户端的默认函数调用顺序

        一般 TCP 客户端调用默认函数的顺序如下:socket() 创建 Socket → connect() 请求连接 → read()/write() 交换数据 → close() 断开连接;

        在服务器端调用 listen() 函数创建连接请求等待队列后,客户端可通过调用 connect() 函数来请求连接;

#include <sys/socket.h>int connect(int sock, struct sockaddr* servaddr, socklen_t addrlen);// sock 表示客户端socket的文件描述符
// servaddr 保存了目标服务器端地址信息
// addrlen 第二个结构体参数 servaddr 的地址变量长度,以字节为单位

4--Linux实现迭代回声服务器端/客户端

服务器端:

// gcc echo_server.c -o echo_server
// ./echo_server 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024
void error_handling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){int serv_sock, clnt_sock;char message[BUF_SIZE];int str_len, i;struct sockaddr_in serv_adr, clnt_adr;socklen_t clnt_adr_sz;if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}serv_sock = socket(PF_INET, SOCK_STREAM, 0);if(serv_sock == -1){error_handling("socket() error");}memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);serv_adr.sin_port = htons(atoi(argv[1]));if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){error_handling("bind() error");}if(listen(serv_sock, 5) == -1){error_handling("listen() error");}clnt_adr_sz = sizeof(clnt_adr);for(i = 0; i < 5; i++){clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);if(clnt_sock == -1){error_handling("accept() error");}else{printf("Connected client %d \n", i+1);}while((str_len = read(clnt_sock, message, BUF_SIZE)) != 0){write(clnt_sock, message, str_len);}close(clnt_sock);}close(serv_sock);return 0;
}

客户端:

// gcc echo_client.c -o echo_client
// ./echo_client 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024void error_handling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){int sock;char message[BUF_SIZE];int str_len;struct sockaddr_in serv_adr;if(argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}sock = socket(PF_INET, SOCK_STREAM, 0);if(sock == -1){error_handling("socket() error");}memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = inet_addr(argv[1]);serv_adr.sin_port = htons(atoi(argv[2]));if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){error_handling("connect() error!");}else{puts("Connected.......");}while(1){fputs("Input message(Q to quit): ", stdout);fgets(message, BUF_SIZE, stdin);if(!strcmp(message, "q\n") || !strcmp(message, "Q\n")){break;}write(sock, message, strlen(message));str_len = read(sock, message, BUF_SIZE-1);message[str_len] = 0;printf("Message from server: %s", message);}close(sock);return 0;
}   

运行结果:

5--Windows实现迭代回声服务器端/客户端

服务器端:

// gcc echo_server_win.c -o echo_server_win -lwsock32
// echo_server_win 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){WSADATA wsaData;SOCKET hServSock, hClntSock;char message[BUF_SIZE];int strLen, i;SOCKADDR_IN servAdr, clntAdr;int clntAdrSize;if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hServSock = socket(PF_INET, SOCK_STREAM, 0);if(hServSock == INVALID_SOCKET){ErrorHandling("socket() error");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = htonl(INADDR_ANY);servAdr.sin_port = htons(atoi(argv[1]));if(bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("bind() error");}if(listen(hServSock, 5) == SOCKET_ERROR){ErrorHandling("listen() error");}clntAdrSize = sizeof(clntAdr);for(int i = 0; i < 5; i++){hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSize);if(hClntSock == -1){ErrorHandling("accept() error");}else{printf("Connected client %d \n", i + 1);}while((strLen = recv(hClntSock, message, BUF_SIZE, 0)) != 0){send(hClntSock, message, strLen, 0);}closesocket(hClntSock);}closesocket(hServSock);WSACleanup();return 0;
}

客户端:

// gcc echo_client_win.c -o echo_client_win -lwsock32
// echo_client_win 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){WSADATA wsaData;SOCKET hSocket;char message[BUF_SIZE];int strLen;SOCKADDR_IN servAdr;if(argc != 3){printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hSocket = socket(PF_INET, SOCK_STREAM, 0);if(hSocket == INVALID_SOCKET){ErrorHandling("socket() error");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = inet_addr(argv[1]);servAdr.sin_port = htons(atoi(argv[2]));if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("connect() error!");}else{puts("Connected........");}while(1){fputs("Input message(Q to quit): ", stdout);fgets(message, BUF_SIZE, stdin);if(!strcmp(message, "q\n") || !strcmp(message, "Q\n")){break;}send(hSocket, message, strlen(message), 0);strLen = recv(hSocket, message, BUF_SIZE - 1, 0);message[strLen] = 0;printf("Message from server: %s", message);}closesocket(hSocket);WSACleanup();return 0;
}

测试结果:

6--TCP原理

I/O缓冲:

        当调用 write() 函数后并不会立即传输数据,而是将数据移至输出缓冲;

        同样当调用 read() 函数后也并不会马上接收数据,而是将数据移至输入缓冲;

        TCP会控制数据流,使用滑动窗口协议(参考博主之前的笔记:TCP流量控制)来限制数据传输不会超过输入缓冲的大小;

TCP 协议使用三次握手来建立连接,使用四次挥手来断开连接;(具体分析参考书中图解)

7--Windows实现计算器服务器端/客户端

服务器端:

// gcc op_server_win.c -o op_server_win -lwsock32
// op_server_win 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024
#define OPSZ 4void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int calculate(int opnum, int opnds[], char op){int result = opnds[0], i;switch(op){case '+':for(i = 1; i < opnum; i++) result += opnds[i];break;case '-':for(i = 1; i < opnum; i++) result -= opnds[i];break;case '*':for(i = 1; i < opnum; i++) result *= opnds[i];break;}return result;
}int main(int argc, char* argv[]){WSADATA wsaData;SOCKET hServSock, hClntSock;char opinfo[BUF_SIZE];int result, opndCnt, i;int recvCnt, recvLen;SOCKADDR_IN servAdr, clntAdr;int clntAdrSize;if(argc != 2){printf("Usage: %s <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hServSock = socket(PF_INET, SOCK_STREAM, 0);if(hServSock == INVALID_SOCKET){ErrorHandling("socket() error!");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = htonl(INADDR_ANY);servAdr.sin_port = htons(atoi(argv[1]));if(bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("bind() error");}if(listen(hServSock, 5) == SOCKET_ERROR){ErrorHandling("listen() error");}clntAdrSize = sizeof(clntAdr);for(int i = 0; i < 5; i++){opndCnt = 0;hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSize);recv(hClntSock, (char*)&opndCnt, 1, 0); // recv one byterecvLen = 0;while((opndCnt * OPSZ + 1) > recvLen){recvCnt = recv(hClntSock, &opinfo[recvLen], BUF_SIZE - 1, 0);recvLen += recvCnt;}result = calculate(opndCnt, (int*)opinfo, opinfo[recvLen - 1]);send(hClntSock, (char*)&result, sizeof(result), 0);closesocket(hClntSock);}closesocket(hServSock);WSACleanup();return 0;
}

客户端:

// gcc op_client_win.c -o op_client_win -lwsock32
// op_client_win 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 1024
#define RLT_SIZE 4
#define OPSZ 4void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char* argv[]){WSADATA wsaData;SOCKET hSocket;char opmsg[BUF_SIZE];int result, opndCnt, i;SOCKADDR_IN servAdr;if(argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandling("WSAStartup() error!");}hSocket = socket(PF_INET, SOCK_STREAM, 0);if(hSocket == INVALID_SOCKET){ErrorHandling("socket() error!");}memset(&servAdr, 0, sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.s_addr = inet_addr(argv[1]);servAdr.sin_port = htons(atoi(argv[2]));if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR){ErrorHandling("connect() error!");}else{puts("Connected........");}fputs("Operand count: ", stdout);scanf("%d", &opndCnt);opmsg[0] = (char)opndCnt; // one bytefor(i = 0; i < opndCnt; i++){printf("Operand %d: ", i + 1);scanf("%d", (int*)&opmsg[i*OPSZ + 1]);}fgetc(stdin);fputs("Operator: ", stdout);scanf("%c", &opmsg[opndCnt * OPSZ + 1]); // one bytesend(hSocket, opmsg, opndCnt * OPSZ + 2, 0);recv(hSocket, (char*)&result, RLT_SIZE, 0);printf("Operation result: %d \n", result);closesocket(hSocket);WSACleanup();return 0;
}

运行结果:

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

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

相关文章

聊聊如何玩转spring-boot-admin

前言 1、何为spring-boot-admin&#xff1f; Spring Boot Admin 是一个监控工具&#xff0c;旨在以良好且易于访问的方式可视化 Spring Boot Actuators 提供的信息 快速开始 如何搭建spring-boot-admin-server 1、在服务端项目的POM引入相应的GAV <dependency><grou…

kali 安装cpolar内网穿透实现 ssh 远程连接

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过cpolar 内网穿透软件实现ssh 远程连接kali! 1. 启动kali ssh 服务 默认新安装的kali系统会关闭ssh 连接服务,我们通…

接入 NVIDIA A100、吞吐量提高 10 倍!Milvus GPU 版本使用指南

Milvus 2.3 正式支持 NVIDIA A100&#xff01; 作为为数不多的支持 GPU 的向量数据库产品&#xff0c;Milvus 2.3 在吞吐量和低延迟方面都带来了显著的变化&#xff0c;尤其是与此前的 CPU 版本相比&#xff0c;不仅吞吐量提高了 10 倍&#xff0c;还能将延迟控制在极低的水准。…

【sgLazyTree】自定义组件:动态懒加载el-tree树节点数据,实现增删改、懒加载及局部数据刷新。

特性 可以自定义主键、配置选项支持预定义节点图标&#xff1a;folder文件夹|normal普通样式多个提示文本可以自定义支持动态接口增删改节点 sgLazyTree源码 <template><div :class"$options.name" v-loading"rootLoading"><div class&qu…

我使用的Vim插件

2023年9月5日&#xff0c;周二下午 为了方便以后还原自己的Vim插件配置&#xff0c;于是写这篇博客来记录一下 不定期更新 目录 语法检查Syntastic文件树The NERD tree自动补全括号auto-pairs超轻量级自动补全vim-auto-popmenu 我使用的插件管理器是vim-plug 语法检查Syntas…

Java学习笔记之----I/O(输入/输出)二

【今日】 孩儿立志出乡关&#xff0c;学不成名誓不还。 文件输入/输出流 程序运行期间&#xff0c;大部分数据都在内存中进行操作&#xff0c;当程序结束或关闭时&#xff0c;这些数据将消失。如果需要将数据永久保存&#xff0c;可使用文件输入/输出流与指定的文件建立连接&a…

GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图

GPT对于每个科研人员已经成为不可或缺的辅助工具&#xff0c;不同的研究领域和项目具有不同的需求。如在科研编程、绘图领域&#xff1a;1、编程建议和示例代码: 无论你使用的编程语言是Python、R、MATLAB还是其他语言&#xff0c;都可以为你提供相关的代码示例。2、数据可视化…

操作系统强化认识之Shell编程学习与总结

目录 1.Shell的概述 2.Shell脚本入门 3.变量 3.1.系统预定义变量 3.2.自定义变量 3.3.特殊变量 4.运算符 5.条件判断 6.流程控制 6.1.if判断 6.2.case语句 6.3.for循环 6.4.while循环 7.read读取控制台输入 8.函数 8.1.系统函数 8.2.自定义函数 9.正则表示式入…

Python,如何安装lap,pip安装lap出现问题

Linux可以&#xff1a; pip install cpython pip install gitgit://github.com/gatagat/lap.gitwindows可以&#xff1a; 下载https://github.com/gatagat/lap 后解压&#xff0c; 安装pip install cpython 安装VS2019企业版&#xff1a; key BF8Y8-GN2QH-T84XB-QVY3B-RC4D…

Python 之 match 表达式

Python 从 3.10 版本开始增加了 match 语句&#xff0c;和其他语言常见的 switch 语句极其相似&#xff0c;但功能更加强大。 本文通过实例&#xff0c;了解下其用法。 基本的 match 语句 def http_code(status): match status: case 400 | 404 | 418: …

1801. 积压订单中的订单总数;1567. 乘积为正数的最长子数组长度;923. 三数之和的多种可能

1801. 积压订单中的订单总数 核心思想&#xff1a;维护一个最小堆sell和一个最大堆buy&#xff0c;然后模拟即可。 1567. 乘积为正数的最长子数组长度 核心思想:动态规划&#xff0c;z表示以当前数字num结尾的乘积为正的最长子数组长度&#xff0c;f表示以当前数字num结尾的乘…

C#循环定时上传数据,失败重传解决方案,数据库标识

有些时候我们需要定时的上传一些数据库的数据&#xff0c;在数据不完整的情况下可能上传失败&#xff0c;上传失败后我们需要定时在重新上传失败的数据&#xff0c;该怎么合理的制定解决方案呢&#xff1f;下面一起看一下&#xff1a; 当然本篇文章只是提供一个思路&#xff0…

postman json复杂数据的模拟

先设置路径 然后可以定义下边数据&#xff08;Key value&#xff09; 也可以不定义 看你的情况 [{"mac": "4C-77-66-19-50-65","addressPattern": "98jd","platform": "ios","registrationId": "…

android studio安卓模拟器高德SDK定位网络连接异常

背景 使用了高德SDK创建了一个 project, 下面是运行界面: 点击 "开始定位"按钮, 结果并没有返回定位信息, 而是报错了: 根据错误提示打开这个网址: https://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode, 并且找到错误码 4 的信息, 显示的是网…

【transformer】自注意力源码解读和复杂度计算

Self-attention A t t e n t i o n ( Q , K , V ) s o f t m a x ( Q K T d k ) V Attention(Q,K,V) softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)softmax(dk​ ​QKT​)V 其中&#xff0c; Q Q Q为查询向量&#xff0c; K K K和 V V V为键向量和值向量&#xff0c;…

油田钻井平台三维应急仿真系统降低事故发生概率

海上钻井是供海上作业人员进行生产作业或者其他活动使用的仿陆地区域&#xff0c;被称为“流动的国土”&#xff0c;主要由上部平台、下浮体(沉垫浮箱)和中部立柱三部分组成&#xff0c;平台上安装钻井、动力、通讯、导航等设备&#xff0c;以及安全救生和人员生活等设施&#…

OB Cloud 初体验

文章来源&#xff1a;韩锋频道 韩锋 数据库行业资深从业者&#xff0c;著有《SQL 优化最佳实践》、《数据库高效优化》等数据库相关著作。 OceanBase&#xff08;下文简称OB&#xff09; 作为国内一款优秀的分布式数据库&#xff0c;这些年来发展很快&#xff0c;在金融、电商…

Java之文件操作与IO

目录 一.认识文件 1.1文件是什么&#xff1f; 1.2文件的组织 1.3文件路径 1.4文件的分类 二.文件操作 2.1File概述 三.文件内容操作--IO 3.1JavaIO的认识 3.2Reader和Writer ⭐Reader类 ⭐Writer类 3.2FileInputStream和FileOutputStream ⭐FileInputStream类 …

继承(个人学习笔记黑马学习)

1、基本语法 #include <iostream> using namespace std; #include <string>//普通实现页面//Java页面 //class Java { //public: // void header() { // cout << "首页、公开课、登录、注册...(公共头部)" << endl; // } // void footer() …

【广州华锐互动】VR全景工厂虚拟导览,虚拟现实技术提升企业数字化信息管理水平

随着工业4.0的到来&#xff0c;VR工厂全景制作成为了越来越多工业企业的选择。传统的工厂管理方式往往存在诸多问题&#xff0c;如信息不对称、安全隐患等。为了解决这些问题&#xff0c;VR工厂全景制作应运而生&#xff0c;它通过结合虚拟现实现实技术和数据采集技术&#xff…