150 Linux 网络编程6 ,从socket 到 epoll整理

1. 只能被一个client 链接 socket例子

此例子用于socket 例子,
该例子只能用于一个客户端连接server。
不能用于多个client 连接  server

socket_server_support_one_clientconnect.c


/*
此例子用于socket 例子,
该例子只能用于一个客户端连接server。
不能用于多个client 连接  server*/
#include "wrap.h"
#define SERVER_PORT 8888int main(int argc, const char* argv[]) {int lfd;// 第一步:创建 lfdlfd = Socket(AF_INET, SOCK_STREAM, 0);// 第二步: 给lfd 绑定 IP 和 PORT,这里需要将 port 和IP 从小端转成大端struct sockaddr_in sockaddrin_server;sockaddrin_server.sin_family = AF_INET;sockaddrin_server.sin_port = htons(SERVER_PORT);sockaddrin_server.sin_addr.s_addr = htonl(INADDR_ANY);Bind(lfd,(struct sockaddr *)&sockaddrin_server,sizeof(sockaddrin_server));//第三步:设定监听上限,这个监听上限的意思是:同时只能有8个客户端和此 server连接,我们这个server只能要一个客户端和我们连接,因此这个值在这里没有具体意义Listen(lfd, 8);// 第四步 :阻塞,并等待客户端连接. accept的第二个参数是传入传出参数,代表的是:成功于服务器连接的客户端的 地址结构struct sockaddr_in sockaddrin_client;socklen_t sockaddrin_clientsocklen_t = sizeof(sockaddrin_client);int  cfd = Accept(lfd, (struct sockaddr *)&sockaddrin_client, &sockaddrin_clientsocklen_t);char clientip[33] = { 0 };const char* clientipresult = inet_ntop(AF_INET, &sockaddrin_client.sin_addr.s_addr, clientip, 32);if (clientipresult == NULL) {printf("inet_ntop error\n");}else {printf("client addr port = %d,addr ip = %s \n", ntohs(sockaddrin_client.sin_port), clientipresult);}printf("client addr port = %d,addr ip = %s \n",ntohs(sockaddrin_client.sin_port), clientip);//只要客户端连接上了, 没有错误,就会走到这一步。//第五步:连接上后,server端就可以循环的 使用read函数 读取客户端发送过来的数据了。//注意的是,read函数默认是阻塞读取的char readbuffer[256] = { 0 };int readbufferlen = 0;while (1) {readbufferlen = Read(cfd, readbuffer, 256);printf("read buffer from client %s \n", readbuffer);for (int i = 0; i < readbufferlen; ++i) {readbuffer[i] = toupper(readbuffer[i]);}Write(cfd, readbuffer, readbufferlen);Write(STDOUT_FILENO, readbuffer, readbufferlen);}
}

wrap.h

#ifndef __WRAP_H_
#define __WRAP_H_#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>void perr_exit(const char* s);
int Accept(int fd, struct sockaddr* sa, socklen_t* salenptr);
int Bind(int fd, const struct sockaddr* sa, socklen_t salen);
int Connect(int fd, const struct sockaddr* sa, socklen_t salen);
int Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);
ssize_t Read(int fd, void* ptr, size_t nbytes);
ssize_t Write(int fd, const void* ptr, size_t nbytes);
int Close(int fd);
ssize_t Readn(int fd, void* vptr, size_t n);
ssize_t Writen(int fd, const void* vptr, size_t n);
ssize_t my_read(int fd, char* ptr);
ssize_t Readline(int fd, void* vptr, size_t maxlen);#endif

wrap.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>void perr_exit(const char* s)
{perror(s);exit(-1);
}int Accept(int fd, struct sockaddr* sa, socklen_t* salenptr)
{int n;again:if ((n = accept(fd, sa, salenptr)) < 0) {if ((errno == ECONNABORTED) || (errno == EINTR))goto again;elseperr_exit("accept error");}return n;
}int Bind(int fd, const struct sockaddr* sa, socklen_t salen)
{int n;if ((n = bind(fd, sa, salen)) < 0)perr_exit("bind error");return n;
}int Connect(int fd, const struct sockaddr* sa, socklen_t salen)
{int n;if ((n = connect(fd, sa, salen)) < 0)perr_exit("connect error");return n;
}int Listen(int fd, int backlog)
{int n;if ((n = listen(fd, backlog)) < 0)perr_exit("listen error");return n;
}int Socket(int family, int type, int protocol)
{int n;if ((n = socket(family, type, protocol)) < 0)perr_exit("socket error");return n;
}ssize_t Read(int fd, void* ptr, size_t nbytes)
{ssize_t n;again:if ((n = read(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}ssize_t Write(int fd, const void* ptr, size_t nbytes)
{ssize_t n;again:if ((n = write(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}int Close(int fd)
{int n;if ((n = close(fd)) == -1)perr_exit("close error");return n;
}/*参三: 应该读取的字节数*/
ssize_t Readn(int fd, void* vptr, size_t n)
{size_t  nleft;              //usigned int 剩余未读取的字节数ssize_t nread;              //int 实际读到的字节数char* ptr;ptr = vptr;nleft = n;while (nleft > 0) {if ((nread = read(fd, ptr, nleft)) < 0) {if (errno == EINTR)nread = 0;elsereturn -1;}else if (nread == 0)break;nleft -= nread;ptr += nread;}return n - nleft;
}ssize_t Writen(int fd, const void* vptr, size_t n)
{size_t nleft;ssize_t nwritten;const char* ptr;ptr = vptr;nleft = n;while (nleft > 0) {if ((nwritten = write(fd, ptr, nleft)) <= 0) {if (nwritten < 0 && errno == EINTR)nwritten = 0;elsereturn -1;}nleft -= nwritten;ptr += nwritten;}return n;
}static ssize_t my_read(int fd, char* ptr)
{static int read_cnt;static char* read_ptr;static char read_buf[100];if (read_cnt <= 0) {again:if ((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {if (errno == EINTR)goto again;return -1;}else if (read_cnt == 0)return 0;read_ptr = read_buf;}read_cnt--;*ptr = *read_ptr++;return 1;
}ssize_t Readline(int fd, void* vptr, size_t maxlen)
{ssize_t n, rc;char    c, * ptr;ptr = vptr;for (n = 1; n < maxlen; n++) {if ((rc = my_read(fd, &c)) == 1) {*ptr++ = c;if (c == '\n')break;}else if (rc == 0) {*ptr = 0;return n - 1;}elsereturn -1;}*ptr = 0;return n;
}

编译命令

gcc socket_server_support_one_clientconnect.c wrap.c -o socket_server_support_one_clientconnect.out
这里使用的是 gcc build, 如果使用g++,则会有build error,因为g++的语法检查,要比 gcc 严格一些。
error 信息如下g++ socket_server_support_one_clientconnect.c wrap.c -o socket_server_support_one_clientconnect.out
wrap.c: In function ‘ssize_t Readn(int, void*, size_t)’:
wrap.c:111:8: error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]ptr = vptr;^~~~
wrap.c: In function ‘ssize_t Writen(int, const void*, size_t)’:
wrap.c:136:8: error: invalid conversion from ‘const void*’ to ‘const char*’ [-fpermissive]ptr = vptr;^~~~
wrap.c: In function ‘ssize_t Readline(int, void*, size_t)’:
wrap.c:180:8: error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]ptr = vptr;

2. 可以被多个 client 链接 socket 例子,使用 父子进程完成

3. 可以被多个 client 链接 socket 例子,使用 子线程完成

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

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

相关文章

C++《AVL树》

在之前的学习当中我们已经了解了二叉搜索树&#xff0c;并且我们知道二叉搜索树的查找效率是无法满足我们的要求&#xff0c;当二叉树为左或者右斜树查找的效率就很低下了&#xff0c;那么这本篇当中我们就要来学习对二叉搜索树进行优化的二叉树——AVL树。在此会先来了解AVL树…

2025年1月21日(树莓派点亮呼吸灯第一次修改)

系统信息&#xff1a; Raspberry Pi Zero 2W 系统版本&#xff1a; 2024-10-22-raspios-bullseye-armhf Python 版本&#xff1a;Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习目标&#xff1a;…

四、华为交换机 STP

生成树协议&#xff08;STP&#xff09;的核心目的是在存在冗余链路的网络中&#xff0c;构建一个无环的拓扑结构&#xff0c;从而防止网络环路带来的广播风暴等问题 一、STP 原理 选举根桥&#xff1a;网络中的每台交换机都会有一个唯一的桥 ID&#xff08;BID&#xff09;&am…

Elasticsearch——Elasticsearch索引管理实战

摘要 本文主要介绍了 Elasticsearch 中索引与索引模板的实战操作。首先讲解了索引管理&#xff0c;包括禁止自动创建索引、索引的格式、创建索引示例、修改索引示例、打开/关闭索引示例、删除索引、查看索引以及 Kibana 管理索引等内容。接着阐述了索引模板管理&#xff0c;涉…

Linux C\C++编程-文件位置指针与读写文件数据块

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客 《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 Linu…

4.JoranConfigurator解析logbak.xml

文章目录 一、前言二、源码解析GenericXMLConfiguratorlogback.xml解析通过SaxEvent构建节点model解析model节点DefaultProcessor解析model 三、总结 一、前言 上一篇介绍了logback模块解析logback.mxl文件的入口, 我们可以手动指定logback.xml文件的位置, 也可以使用其它的名…

leetcode刷题记录(七十八)——105. 从前序与中序遍历序列构造二叉树

&#xff08;一&#xff09;问题描述 105. 从前序与中序遍历序列构造二叉树 - 力扣&#xff08;LeetCode&#xff09;105. 从前序与中序遍历序列构造二叉树 - 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一…

包文件分析器 Webpack Bundle Analyzer

webpack-bundle-analyzer 是一个非常有用的工具&#xff0c;用于可视化和分析 Webpack 打包生成的文件。这使得开发者能够更好地理解应用的依赖关系、包的大小&#xff0c;以及优化打包的机会。以下是关于 webpack-bundle-analyzer 的详细介绍&#xff0c;包括它的安装、使用以…

【PowerQuery专栏】PowerQuery提取XML数据

XML数据和Json 数据类型都是比较典型的层次数据类型,XML的数据格式非常的对称。所有的数据均是由标签对组成,图为典型的XML文件类型的数据。 在PowerQuery中进行XML数据类型解析采用的是Xml.Document 函数来进行文件内容的解析,Xml.Document 目前有三个可用参数。 参数1为数…

1.21学习记录

misc 2023isctf 你说爱我尊嘟假嘟 这题有点脑洞&#xff0c;需要把你说爱我换成Ook.将尊嘟换为Ook&#xff01;假嘟换成Ook&#xff1f;&#xff08;根据语气进行猜测吧&#xff09;用在线工具解密最后用base64解密即可 2023isctf 杰伦可是流量明星 解压后是一个MP3文件&am…

leetcode_字符串 459. 重复的子字符串

459. 重复的子字符串 给定一个非空的字符串s&#xff0c;检查是否可以通过由他的一个子串重复多次构成思路&#xff1a; 首先判断字符串s是否为空或长度是否为1&#xff0c;若满足这两种条件&#xff0c;则说明不存在子字符串&#xff0c;返回False遍历所有可能的子串&#xf…

如何将自己本地项目开源到github上?

环境&#xff1a; LLMB项目 问题描述&#xff1a; 如何将自己本地项目开源到github上&#xff1f; 解决方案&#xff1a; 步骤 1: 准备本地项目 确保项目整洁 确认所有的文件都在合适的位置&#xff0c;并且项目的 README.md 文件已经完善。检查是否有敏感信息&#xff0…

【MySQL】数据库基础知识

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;【MySQL】数据库基础知识 发布时间&#xff1a;2025.1.21 隶属专栏&#xff1a;MySQL 目录 什么是数据库为什么要有数据库数据库的概念 主流数据库mysql的安装mysql登录使用一下mysql显示数据库内容创建一个数据库创…

优化使用 Flask 构建视频转 GIF 工具

优化使用 Flask 构建视频转 GIF 工具 优化后的项目概述 在优化后的版本中&#xff0c;我们将实现以下功能&#xff1a; 可设置每个 GIF 的帧率和大小&#xff1a;用户可以选择 GIF 的帧率和输出大小。改进的用户界面&#xff1a;使用更现代的设计使界面更美观、整洁。自定义…

R 语言 | future 包,非阻塞的执行耗时脚本

目的&#xff1a;有一段代码&#xff0c;后面暂时用不到&#xff0c;但是又很耗时&#xff0c;占了当前R session&#xff0c;难道只能等半个小时&#xff0c;等到它结束才能画图&#xff1f; 可以使用R多线程&#xff0c;在支线中执行耗时任务&#xff0c;同时不阻塞当前R进程…

使用插件SlideVerify实现滑块验证

作者gitee地址&#xff1a;https://gitee.com/monoplasty/vue-monoplasty-slide-verify 使用步骤&#xff1a; 1、安装插件 npm install --save vue-monoplasty-slide-verify 2、在main.js中进行配置 import SlideVerify from vue-monoplasty-slide-verify; Vue.use(SlideV…

Windows配置frp内网穿透实现远程连接

仅个人记录 本文仅介绍客户端的配置 1. 开始 frp分为服务端和客户端&#xff0c;为实现内网穿透需要同时配置服务端和客户端&#xff0c;并且版本保持一致&#xff0c;可以前往 frp github下载 本文使用 0.51.2 版本&#xff0c;从GitHub下载并解压&#xff0c;得到如下文件…

“大模型横扫千军”背后的大数据挖掘--浅谈MapReduce

文章目录 O 背景知识1 数据挖掘2 邦费罗尼原则3 TF.IDF4 哈希函数5 分布式文件系统 一、MapReduce基本介绍1. Map 任务2. 按键分组3. Reduce 任务4. 节点失效处理5.小测验&#xff1a;在一个大型语料库上有100个map任务和若干reduce任务&#xff1a; 二、基于MapReduce的基本运…

第17个项目:Python烟花秀

源码下载地址:https://download.csdn.net/download/mosquito_lover1/90295693 核心源码: import pygame import random import math from PIL import Image import io # 初始化pygame pygame.init() # 设置窗口 WIDTH = 800 HEIGHT = 600 screen = pygame.display.s…

GDB相比IDE有什么优点

GDB(GNU Debugger)相比于集成开发环境(IDE)具有一些独特的优点,主要体现在其灵活性、可定制性和低级控制能力。具体来说,GDB有以下几个优点: 1. 轻量级且无依赖 GDB是一个命令行工具,不依赖于任何复杂的图形界面或大型库,这使得它非常适合在资源受限的环境中使用,比…