Linux 网络编程 tcp server 笔记

news2024/11/13 15:58:49

一、TCP 服务器的创建

在 Linux 上创建一个简单的 tcp 服务器步骤如下:

①创建套接字

②将套接字绑定到 IP 地址和端口号

③监听来自客户端的连接

④接受连接并创建新的套接字用于与客户端通信

⑤通过新建的套接字发送和接收数据

⑥关闭套接字

流程框图如下:

7e06856095275adf66b6fb22f68a0c3b.png

根据以上介绍可以创建tcp server的示例,分为服务器-单客户端和服务器-多客户端。

二、服务器-单客户端示例

tcp server示例代码如下:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> //struct sockaddr_in
#include <arpa/inet.h> //inet_addr()
#include <unistd.h>//close()




#define MY_PRINTF(argv)   do{\
                                printf("file:%s --- function:%s --- line:%d\r\n",__FILE__,__FUNCTION__,__LINE__);\
                                printf("%s\r\n",argv);\
                            }while(0);
#define MYPORT 5000
//tcp server demo
 int main(int argc,char *argv[])
{
     int sockefd;
     int sockenewfd;
     int ret;
     int enable=1;


     struct sockaddr_in my_addr;//本地地址-服务器


     struct sockaddr_in remote_addr;//远端地址-客户端
     int remote_addr_len;


     char buf[1024];


     sockefd=socket(AF_INET,SOCK_STREAM,0);// 套接字
     if(sockefd<0)
     {
         MY_PRINTF("socket err !! ");
         return -1;
     }
    if (setsockopt(sockefd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable)) == -1) 
     {
        close(sockefd);
        MY_PRINTF(" setsockopt  err !! ");
        return -1;
    }
     MY_PRINTF("socket ok !! ");


     //本地地址
     my_addr.sin_family=AF_INET;    
     my_addr.sin_port=htons(MYPORT);//0:随机端口
     my_addr.sin_addr.s_addr=INADDR_ANY;//inet_addr("192.168.164.157");//INADDR_ANY:本机 ip  // inet_addr():IP 地址的字符串转换成一个无符号长整型
     bzero(my_addr.sin_zero,sizeof(my_addr.sin_zero));




     ret=bind(sockefd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));//绑定   //转换数据类型
     if(ret<0)
     {
         close(sockefd);
         MY_PRINTF("bind err !! ");
         return -1;
     }
     MY_PRINTF("bind ok !! ");


     ret=listen(sockefd,5);//监听
     if(ret<0)
     {
         close(sockefd);
         MY_PRINTF("listen err !! ");
         return -1;
     }
     MY_PRINTF("listen ok !! ");


     sockenewfd=accept(sockefd,(struct sockaddr *)&remote_addr,&remote_addr_len);//获取连接的新套接字
     if(sockenewfd<0)
     {
         close(sockefd);
         MY_PRINTF("accept err !! ");
         return -1;
     }
     MY_PRINTF("accept ok !! ");


    printf("%d\r\n",ntohs(remote_addr.sin_port));  //端口号
    printf("%s\r\n",inet_ntoa(remote_addr.sin_addr));//ip地址    //转换为字符串形式以 数字.数字.数字.数字 的格式显 示出来


     for(;;)
     {
            ret=recv(sockenewfd,buf,sizeof(buf),0);//接收
            if(ret<0)
            {
                close(sockenewfd);
                MY_PRINTF("recv err !! ");
                break;
            }
            else if(ret==0)
            {
                close(sockenewfd);
                MY_PRINTF("close !! ");
                perror("close sockenewfd");  
                break;
            }
            MY_PRINTF("recv ok !! ");
            MY_PRINTF(buf);


            ret=send(sockenewfd,buf,ret,0);//发送 等价于write(sockenewfd,buf,ret);
            if(ret<0)
            {
                MY_PRINTF("send err !! ");
            }
            MY_PRINTF("send ok !! ");
            MY_PRINTF(buf);
     }




      close(sockefd);//关闭
      perror("close sockefd");
      return0;


 }

程序运行只允许单个客户端连接通讯。测试如下:

服务端启动,等待连接,如下:

50959d4753910442cafe7bf93bfb25fa.png

客户端连接,如下:

9c044a0cc3c0414d814cab194431c141.png

服务端获取到客户端连接,如下:

499390968ee107bb269ebe68b9b98bce.png

客户端发送数据,并接收到服务端返回,如下:

fe6c0bd29696559425a8169907429e7e.png

服务端显示:

bddbe154b449fa7b1c1eb62af765d2fc.png

三、服务器-多客户端

这里介绍两种方法,方法一:使用多线程;方法二:使用select方法。

①方法一多线程,测试代码如下:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> //struct sockaddr_in
#include <arpa/inet.h> //inet_addr()
#include <unistd.h>//close()




#define MY_PRINTF(argv)   do{\
                                printf("file:%s --- function:%s --- line:%d\r\n",__FILE__,__FUNCTION__,__LINE__);\
                                printf("%s\r\n",argv);\
                            }while(0);
#define MYPORT 5000
//tcp server demo




void *myfun_thread(void *socketInfo)
{
    char buf[1024];
     int ret;
    int sockenewfd=(int)socketInfo;


     for(;;)
     {
            ret=recv(sockenewfd,buf,sizeof(buf),0);//接收
            if(ret<0)
            {
                  close(sockenewfd);
                MY_PRINTF("recv err !! ");
                perror("close sockenewfd");  
                break;
            }
            else if(ret==0)
            {
                close(sockenewfd);
                MY_PRINTF("close !! ");
                perror("close sockenewfd");  
                break;
            }
            MY_PRINTF("recv ok !! ");
            MY_PRINTF(buf);


            ret=send(sockenewfd,buf,ret,0);//发送 等价于write(sockenewfd,buf,ret);
            if(ret<0)
            {
                MY_PRINTF("send err !! ");
            }
            MY_PRINTF("send ok !! ");
            MY_PRINTF(buf);
     }
     pthread_exit(NULL);


}


 int main(int argc,char *argv[])
{
     int sockefd;
     int sockenewfd;
     int ret;
     int enable=1;
     pthread_t  threadRx;
     struct sockaddr_in my_addr;//本地地址-服务器


     struct sockaddr_in remote_addr;//远端地址-客户端
     int remote_addr_len;


     


     sockefd=socket(AF_INET,SOCK_STREAM,0);// 套接字
     if(sockefd<0)
     {
         MY_PRINTF("socket err !! ");
         return -1;
     }
     if (setsockopt(sockefd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable)) == -1) 
     {
        close(sockefd);
        MY_PRINTF(" setsockopt  err !! ");
        return -1;
    }
     MY_PRINTF("socket ok !! ");


     //本地地址
     my_addr.sin_family=AF_INET;    
     my_addr.sin_port=htons(MYPORT);//0:随机端口
     my_addr.sin_addr.s_addr=INADDR_ANY;//inet_addr("192.168.164.157");//INADDR_ANY:本机 ip  // inet_addr():IP 地址的字符串转换成一个无符号长整型
     bzero(my_addr.sin_zero,sizeof(my_addr.sin_zero));


    
     ret=bind(sockefd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));//绑定   //转换数据类型
     if(ret<0)
     {
         close(sockefd);
         MY_PRINTF("bind err !! ");
         return -1;
     }
     MY_PRINTF("bind ok !! ");


     ret=listen(sockefd,5);//监听
     if(ret<0)
     {
         close(sockefd);
         MY_PRINTF("listen err !! ");
         return -1;
     }
     MY_PRINTF("listen ok !! ");


     while(1)
     {
                sockenewfd=accept(sockefd,(struct sockaddr *)&remote_addr,&remote_addr_len);//获取连接的新套接字
                if(sockenewfd<0)
                {
                    MY_PRINTF("accept err !! ");
                    break;
                }
                MY_PRINTF("accept ok !! ");


                printf("%d\r\n",ntohs(remote_addr.sin_port));  //端口号
                printf("%s\r\n",inet_ntoa(remote_addr.sin_addr));//ip地址    //转换为字符串形式以 数字.数字.数字.数字 的格式显 示出来
                pthread_create(&threadRx, NULL, myfun_thread, (void *)sockenewfd);
                sleep(1);
     }
     close(sockefd);//关闭
    perror("close sockefd");  
     return 0;


 }

测试结果:

服务端:

2eedde70a977fc5d02db9ac76f735503.png

客户端:

5cf7c32b0cfbd080d17623fc87289453.png

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

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

相关文章

AI 法律助手与原创奇幻小说生成 | 开源专题 No.33

eosphoros-ai/DB-GPT Stars: 6.4k License: MIT DB-GPT是一个实验性的开源项目&#xff0c;利用本地化的GPT大型模型与数据和环境进行交互&#xff0c;旨在提供私密性和安全性的数据处理解决方案。 主要功能: SQL语言能力SQL生成和诊断私有领域问答和数据处理知识管理&#x…

AIGC Excel办公应用实现行与列交叉多条件求和

这样的一个多条件求和函数的应用,我们可以使用ChatGPT,OpenAI,人工智能来实现。 Prompt提示词: 有一个表格A3至A186为部门,B3至B186为月份,D3至D186为费用,请根据G2单元格的月份与F3的部门汇总费用,写出Excel函数公式,并且加上绝对引用与相对引用,可以向右填充与向…

在北欧设计中,有种轻奢叫石膏线。福州中宅装饰,福州装修

很多人在追求精致的路上&#xff0c; 大都选择一个喜欢的城市&#xff0c; 小到睫毛也要刷出太阳花。 在家装中&#xff0c;我们也追求更精致的家居生活。 现如今石膏线的运用也很广泛 有一个不起眼的东西&#xff0c; 它对于家装的精致感提升&#xff0c; 起到了画龙点…

Echarts图例图标和文字居中

前言&#xff1a;设置了verticalAlign:"middle"&#xff0c;lineHeight&#xff0c;效果没有生效&#xff0c;然后通过设置文本的padding&#xff0c;实现居中。 代码实现&#xff1a;

FPGA面试题(3)

一.FPGA和CPLD区别 FPGA&#xff1a;现场可编程门阵列CPLD&#xff1a;复杂可编程逻辑器件 二.多位异步信号如何同步 单比特异步信号 慢时钟域->快时钟域&#xff1a;同步打拍快时钟域->慢时钟域&#xff1a;先拓展位宽再同步打拍 多比特异步信号 1.异步FIFO2.保持…

vs code 添加vue3代码模板方法

最终效果 vs code 添加vue文件模板用于通过简写自动生成代码 操作步骤如下 1.找到vue模板代码编写入口 2.修改模板内容 2.1 vue.json内容 {// Place your snippets for vue here. Each snippet is defined under a snippet name and has a prefix, body and// description. T…

生信学院|10月13日《SOLIDWORKS参数化应用——DriveWorksXpress》

课程主题&#xff1a;SOLIDWORKS参数化应用——DriveWorksXpress 课程时间&#xff1a;2023年10月13日 14:00-14:30 主讲人&#xff1a;温晓露 生信科技 售后服务工程师 1、DriveWorks的作用 2、用 DriveWorksXpress 自动化您的设计过程 3、Drive Works Xpress最佳做法 4…

Matlab地理信息绘图—研究区域绘制

文章目录 m_map工具箱Matlab绘制研究区域结果显示 m_map工具箱 m_map是 MATLAB 中用于制作地图和地理数据可视化的工具包。这个工具包提供了一组函数和工具&#xff0c;使得用户能够在 MATLAB 中轻松创建地图&#xff0c;并在地图上显示各种地理和气象数据。以下是 m_map 工具包…

nginx在windows下按照

Windows下Nginx的启动、停止等命令 可以进入到nginx的安装根目录&#xff0c;执行nginx.exe -h 在Windows下使用Nginx&#xff0c;我们需要掌握一些基本的操作命令&#xff0c;比如&#xff1a;启动、停止Nginx服务&#xff0c;重新载入Nginx等&#xff0c;下面我就进行一些简…

数仓面试题(1)

1.数据库的三范式是什么&#xff1f; 答&#xff1a; 第一范式&#xff08;1NF&#xff09; 强调的是列的原子性&#xff0c;即列不能够再分成其他几列。 第二范式&#xff08;2NF&#xff09; 第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列…

海豚调度器集群安装DolphinScheduler(3.1.8)

一、前置准备工作 JDK:下载JDK (1.8),安装并配置 JAVA_HOME 环境变量,并将其下的 bin 目录追加到 PATH 环境变量中。如果你的环境中已存在,可以跳过这步。海豚调度器二进制包:下载 DolphinScheduler(3.1.8) 二进制包数据库: MySQL (5.7)注册中心:ZooKeeper (3.9.0)进程树…

CPU性能分析--火焰图使用

记录工具使用说明&#xff0c;火焰图原理网上分析很多。主要用来分析函数调用栈占用的cpu利用率&#xff0c;分析函数性能。 perf安装&#xff1a; sudo apt-get install linux-tools-common sudo apt-get install linux-tools-"(uname -r)" sudo apt-get install …

【广州华锐互动】铝厂事故3D仿真还原让员工深刻认识事故严重性

铝厂作为高风险行业&#xff0c;安全问题一直备受关注。随着3D技术的不断发展&#xff0c;铝厂开始采用3D警示动画进行安全教育&#xff0c;取得了显著的成效。这种逼真的画面能够让员工深刻认识到事故的严重性和危害性&#xff0c;从而更加重视安全问题。 1.分析事故原因和后果…

用netty实现简易rpc

文章目录 rpc介绍&#xff1a;rpc调用流程:代码&#xff1a; rpc介绍&#xff1a; RPC是远程过程调用&#xff08;Remote Procedure Call&#xff09;的缩写形式。SAP系统RPC调用的原理其实很简单&#xff0c;有一些类似于三层构架的C/S系统&#xff0c;第三方的客户程序通过接…

群晖内安装的windows虚拟机如何扩展磁盘(虚拟机如何扩展磁盘,解决扩展磁盘不生效的问题)

文章目录 问题解决问题问题 在群晖的虚拟机中创建了一个Win7x64的虚拟机,由于配置低的原因,但是容量只设置了30G,但是现在要满了,所以现在要迁移和扩容 迁移很简单,直接选择迁移就行,扩容的话也就是选择扩容到指定的容量 (注意:这里容量扩大是不可逆的,扩大了不能再变…

银河麒麟安装arm架构mysql8

1. 准备工作 2. 查看麒麟系统版本 使用命令 Linux version 4.19.90-25.21.v2101.ky10.aarch64 (KYLINSOFTlocalhost.localdomain) (gcc version 7.3.0 (GCC)) #1 SMP Wed Sep 28 16:37:42 CST 2022可以看出这是麒麟 v10 &#xff0c;aarch64 &#xff08;ARM 架构的&#xff…

A股风格因子看板 (2023.10 第02期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格暴露等。 今日为该因子跟踪第02期&#xff0c;指数组合数据截止日2023-09-30&#xff0c;要点如下 1) 近1年A股风格因子检…

聊一聊 Spring 6 面向切面AOP

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 今天我们一起看看Spring AOP的相关操作&#xff01; 1、场景模拟 搭建子模块&#xff1a;spring6-aop 1.1、声明接口 声明计算器接口Calculator&#xff0c;包含加减乘除的抽象方法 public interface Calculator…

tailwindcss安装完插件代码不提示

安装完插件鼠标滑过tailwindcss类名claa不提示 vscode版本太低.需要安装最新的vscode插件扩展设置中的Tailwind CSS :Emmet Completions默认是未勾选的,需要手动勾选

科技云报道:不堪忍受英伟达霸权,微软、OpenAI纷纷自研AI芯片

科技云报道原创。 英伟达是当之无愧的“AI算力王者”&#xff0c;A100、H100系列芯片占据金字塔顶尖位置&#xff0c;是ChatGPT这样的大型语言模型背后的动力来源。 但面对英伟达的独霸天下&#xff0c;科技巨头们都纷纷下场自研AI芯片。 10月6日&#xff0c;媒体援引知情人…