Linux高阶——1117—TCP客户端服务端

目录

1、sock.h

socket常用函数

网络初始化函数

首次响应函数

测试IO处理函数

 获取时间函数

总代码

2、sock.c

SOCKET()

ACCEPT()——服务端使用这个函数等待客户端连接

 CONNECT()——客户端使用这个函数连接服务端

BIND()——一般只有服务端使用

LISTEN()——服务端使用

RECV()

SEND()

net_initializer()——网络初始化函数

get_time()——获取时间函数

first_response()——首次适应函数

总代码

3、生成网络动态库

客户端代码

服务端代码

成功截图


1、sock.h

socket常用函数

int ACCEPT(int,struct sockaddr*,socklen_t *); 
int SOCKET(int,int,int);
ssize_t RECV(int,void*,size_t,int);
int CONNECT(int, const struct sockaddr *,socklen_t);
int BIND(int, const struct sockaddr *,socklen_t);
int LISTEN(int, int backlog);
ssize_t SEND(int, const void *, size_t, int);

网络初始化函数

int net_initializer(const char*,int,int);

首次响应函数

int first_response(client_info);

测试IO处理函数

int test_business(int);

 获取时间函数

int get_time(char* tm);

总代码

#ifndef _MYSOCK_
#define _MYSOCK_
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<netdb.h>
#include<errno.h>
#include<time.h>
#include<stdio.h>
#endif

typedef struct
{
    int sockfd;
    int port;
    char ip[16];
}client_info;

int ACCEPT(int,struct sockaddr*,socklen_t *); 
int SOCKET(int,int,int);
ssize_t RECV(int,void*,size_t,int);
int CONNECT(int, const struct sockaddr *,socklen_t);
int BIND(int, const struct sockaddr *,socklen_t);
int LISTEN(int, int backlog);
ssize_t SEND(int, const void *, size_t, int);

int net_initializer(const char*,int,int);
int first_response(client_info);
int test_business(int);
int get_time(char* tm);

2、sock.c

SOCKET()

SOCKET(socket协议域,数据传输层使用协议模式,指定具体的协议)

int SOCKET(int domain,int type,int protocal)
{
    int fd; 
    if((fd=socket(domain,type,protocal))==-1)
    {
        perror("socket call failed");
        return fd; 
    }   
    return fd; 
}

ACCEPT()——服务端使用这个函数等待客户端连接

ACCEPT(服务端socket,客户端的网络信息结构体,客户端网络信息结构体长度) ——客户端接收数据

int ACCEPT(int sockfd,struct sockaddr* addr,socklen_t * addrlen)
{
    int fd; 
    if((fd=accept(sockfd,addr,addrlen))==-1)
    {
        perror("accept call failed");
        return fd; 
    }   
    return fd; 
}

 CONNECT()——客户端使用这个函数连接服务端

客户端只有一个socket

CONNECT(用于连接的socket,目标信息结构体,目标信息结构体长度)

int CONNECT(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
{
    int fd;
    if((fd=connect(sockfd,addr,addrlen))==-1)
    {
        perror("connect call failed");
        return fd;
    }
    return fd;
}

BIND()——一般只有服务端使用

BIND(需要绑定的socket,网络信息结构体的地址,网络信息结构体的长度)

int BIND(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
{
    int fd;
    if((fd=bind(sockfd,addr,addrlen))==-1)
    {
        perror("bind call failed");
        return fd;
    }
    return fd;
}

LISTEN()——服务端使用

LISTEN(服务端socket,等待连接队列的最大长度)

int LISTEN(int sockfd, int backlog)
{
    int fd;
    if((fd=listen(sockfd, backlog))==-1)
    {
        perror("listen call failed");
        return fd;
    }
    return fd;
}

RECV()

RECV(套接字sockfd,数据buf,数据长度size,选项,发送的长度)

对于服务端,sockfd是accept函数的返回值

对于客户端,sockfd是connect函数的返回值

ssize_t RECV(int sockfd,void* buf,size_t len,int flag)
{
    ssize_t fd; 
    if((fd=recv(sockfd,buf,len,flag))==-1)
    {
        perror("recv call failed");
        return fd; 
    }   
    return fd; 
}

SEND()

SEND(发送的人的sockfd,数据buf,数据包长度)

ssize_t SEND(int sockfd, const void *buf, size_t len, int flags)
{
    ssize_t fd;
    if((fd=send(sockfd,buf,len,flags))==-1)
    {
        perror("send call failed");
        return fd;
    }
    return fd;
}

net_initializer()——网络初始化函数

net_initializer(ip地址,端口号,可以监听队列的最大长度)

int net_initializer(const char* ip,int port,int backlog)
{
    int sockfd;
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=inet_addr("82.157.31.74");
    sockfd=SOCKET(AF_INET,SOCK_STREAM,0);
    BIND(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    LISTEN(sockfd,backlog);
    return sockfd;
}

get_time()——获取时间函数

get_time(时间数组)

int get_time(char* tm)
{
    bzero(tm,1024);
    time_t tp;
    tp=time(NULL);
    ctime_r(&tp,tm);
    tm[strlen(tm)-1]='\0';
    return 0;
}

first_response()——首次适应函数

first_response(定义的结构体)

client_info——定义的结构体——包含port,ip,和创建的套接字

typedef struct
{
    int sockfd;
    int port;
    char ip[16];
}client_info;
int first_response(client_info cf)
{
    char response[1500];
    bzero(response,1500);
    char tm[1024];
    get_time(tm);
    printf("Server,output info,client ip %s,client port %d\n",cf.ip,cf.port);
    SEND(cf.sockfd,response,strlen(response),MSG_NOSIGNAL);
    return 0;
}

总代码

#include<sock.h>

int ACCEPT(int sockfd,struct sockaddr* addr,socklen_t * addrlen)
{
    int fd; 
    if((fd=accept(sockfd,addr,addrlen))==-1)
    {
        perror("accept call failed");
        return fd; 
    }   
    return fd; 
}

int SOCKET(int domain,int type,int protocal)
{
    int fd; 
    if((fd=socket(domain,type,protocal))==-1)
    {
        perror("socket call failed");
        return fd; 
    }   
    return fd; 
}

ssize_t RECV(int sockfd,void* buf,size_t len,int flag)
{
    ssize_t fd; 
    if((fd=recv(sockfd,buf,len,flag))==-1)
    {
        perror("recv call failed");
        return fd; 
    }   
    return fd; 
}

int CONNECT(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
{
    int fd;
    if((fd=connect(sockfd,addr,addrlen))==-1)
    {
        perror("connect call failed");
        return fd;
    }
    return fd;
}

int BIND(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
{
    int fd;
    if((fd=bind(sockfd,addr,addrlen))==-1)
    {
        perror("bind call failed");
        return fd;
    }
    return fd;
}

int LISTEN(int sockfd, int backlog)
{
    int fd;
    if((fd=listen(sockfd, backlog))==-1)
    {
        perror("listen call failed");
        return fd;
    }
    return fd;
}

ssize_t SEND(int sockfd, const void *buf, size_t len, int flags)
{
    ssize_t fd;
    if((fd=send(sockfd,buf,len,flags))==-1)
    {
        perror("send call failed");
        return fd;
    }
    return fd;
}


int net_initializer(const char* ip,int port,int backlog)
{
    int sockfd;
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=inet_addr("82.157.31.74");
    sockfd=SOCKET(AF_INET,SOCK_STREAM,0);
    BIND(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    LISTEN(sockfd,backlog);
    return sockfd;
}

int get_time(char* tm)
{
    bzero(tm,1024);
    time_t tp;
    tp=time(NULL);
    ctime_r(&tp,tm);
    tm[strlen(tm)-1]='\0';
    return 0;
}

int first_response(client_info cf)
{
    char response[1500];
    bzero(response,1500);
    char tm[1024];
    get_time(tm);
    printf("Server,output info,client ip %s,client port %d\n",cf.ip,cf.port);
    SEND(cf.sockfd,response,strlen(response),MSG_NOSIGNAL);
    return 0;
}

3、生成网络动态库

将所有的.c或.cpp变成可重定位二进制文件(载入库数据时,查找可用内存,而不是固定地址)

生成可重定位的二进制文件.o——gcc test.c -fPIC -I头文件路径 -c

gcc sock.c -I./ -fPIC -c

生成.so库——gcc xxx.o -shared -fPIC -I头文件 -o libmysock.so

共享库名,线程库里为-lpthread,内存中为libpthread.so

gcc sock.o -shared -fPIC -I./ -o libmysock.so

生成库后,需要使用-L指定库位置——gcc x.c -I头文件 -L 库路径 -lmysock -o app

如果共享库已经在默认/usr/lib位置,编译时无需-L参数

查看程序所依赖的库文件,查看未加载成功的库名——ldd 程序名

ldd app

将共享库.so文件复制到/usr/lib/——mv libname.so /usr/lib/

在linux操作系统下,使用ifconfig命令查看本机私有ip地址,如果本机写服务器使用本机ip

成功后,可以直接使用./程序名运行程序

客户端代码

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

#define server_ip "192.168.5.133"
#define server_port 9090

int main()
{
    struct sockaddr_in client_addr;
    bzero(&client_addr,sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(server_port);
    client_addr.sin_addr.s_addr = inet_addr(server_ip);
    inet_pton(AF_INET,server_ip,&client_addr.sin_addr.s_addr);

    int client_sock;
    if((client_sock=socket(AF_INET,SOCK_STREAM,0))==-1)
    {   
        perror("sock create failed");
        return -1; 
    }   

    socklen_t addrlen;
    char recvv[1024];
    printf("TCP IO Client Running...\n");
    addrlen = sizeof(client_addr);
    if((connect(client_sock, (struct sockaddr*)&client_addr, addrlen))==-1)
    {   
        perror("failed");
        return -1; 
    }   
    bzero(recvv,sizeof(recvv));
    printf("client sock %d\n",client_sock);
    int len=recv(client_sock,recvv,sizeof(recvv),0);
    
    if(len==-1)
        perror("recv call failed");
    printf("len %d  %s\n",len, recvv);
    close(client_sock);
}

服务端代码

#include<sock.c>
#define server_ip "192.168.5.133"
#define server_port 9090

int main()
{
    struct sockaddr_in client_addr;
    int server_sock;
    int client_sock;
    server_sock=net_initializer(NULL,server_port,128);
    socklen_t addrlen;
    printf("TCP IO Servers Running...\n");
    char cip[16];
    ssize_t len;
    client_info cf;
    char buf[1500];
    char* msg="Please try again\n";
    char tm[1024];

    while(1)
    {
        addrlen=sizeof(client_addr);
        client_sock=ACCEPT(server_sock,(struct sockaddr*)&client_addr,&addrlen);
        cf.sockfd=client_sock;
        inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,cf.ip,16);
        cf.port=ntohs(client_addr.sin_port);
        first_response(cf);
        while((len=RECV(client_sock,buf,sizeof(buf),0))>0)
        {
            if((strcmp(buf,"time\n"))==0)
            {
                get_time(tm);
                SEND(client_sock,tm,strlen(tm),MSG_NOSIGNAL);
                bzero(tm,sizeof(tm));
            }
            else
        {
            SEND(client_sock,msg,strlen(msg),MSG_NOSIGNAL);
        }
        bzero(buf,sizeof(buf));
    }
    if(len==0)
    {
        printf("client exit\n");
        close(client_sock);
    }
    }
    close(server_sock);
    printf("server done\n");
    return 0;
}

成功截图

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

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

相关文章

1.5万字长文Java集合与数据结构面试题(注:该篇博客将会持续维护 最新维护时间:2024年11月25日)

&#x1f9f8;本篇博客重在讲解Java集合与数据结构面试题&#xff0c;将会实时更新&#xff0c;欢迎大家添加作者文末联系方式交流 &#x1f4dc;JAVA面试题专栏&#xff1a;JAVA崭新面试题——2024版_dream_ready的博客-CSDN博客 &#x1f4dc;作者首页&#xff1a; dream_rea…

[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式

T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求&#xff1a; 编译硬件需求&#xff1a;做多系统测试&#xff0c;磁盘500GB起步(固态)&#xff08;机械会卡死&#xff09;&#xff0c;内存3…

40分钟学 Go 语言高并发:【实战】并发安全的配置管理器

【实战】并发安全的配置管理器 一、课程概述 学习要点重要程度掌握目标配置热更新★★★★★理解配置热更新原理&#xff0c;实现动态加载配置并发读写控制★★★★★掌握并发安全的读写控制机制观察者模式★★★★☆理解并实现配置变更通知机制版本管理★★★★☆实现配置版…

游戏陪玩系统开发功能需求分析

电竞游戏陪玩系统是一种专门为游戏玩家提供陪伴、指导和互动服务的平台。这类系统通常通过专业的陪玩师&#xff08;也称为陪练师&#xff09;为玩家提供一对一或多对一的游戏陪伴服务&#xff0c;帮助玩家提升游戏技能、享受游戏乐趣&#xff0c;甚至解决游戏中的各种问题。电…

Idea修改Commit Changes模式、idea使用git缺少部分Commit Changes

文章目录 一、模式一1、页面效果如下2、如何打开为这种样式&#xff1f; 二、模式二1、页面效果如下2、如何打开为这种样式&#xff1f; 三、总结 前言&#xff1a;Idea中代码提交到git库时的commit Change有两种模式&#xff0c;每种模式的界面及功能都不太一样。 Commit Cha…

飞书会话消息左右排列

飞书会话消息左右排列 1. 飞书登录后&#xff0c;点击头像&#xff0c;弹出菜单有个按钮设置 2. 3.

VUE3项目 关于金额:分转化为元 ;元转化为分;

1.在components 文件夹下新建moneyHandle.ts 文件 2.ts文件中写如下代码&#xff08;保留两位小数&#xff09; //分转化为元 - 正则解决精度 export const regFenToYuan (fen:any) >{var num fen;numfen*0.01;num;var reg num.indexOf(.) >-1 ? /(\d{1,3})(?(?:…

【linux学习指南】初识Linux进程信号与使用

文章目录 &#x1f4dd;信号快速认识&#x1f4f6;⽣活⻆度的信号&#x1f4f6; 技术应⽤⻆度的信号&#x1f309; 前台进程&#xff08;键盘&#xff09;&#x1f309;⼀个系统函数 &#x1f4f6;信号概念&#x1f4f6;查看信号 &#x1f320; 信号处理&#x1f309; 忽略此信…

蒙特卡洛方法(Monte Carlo,MC)

目录 1 序言 2 Monte Carlo法计算积分 3 最优化计算Monte Carlo法 1 序言 蒙特卡罗方法(Monte Carlo)是由冯诺依曼和乌拉姆等人发明的&#xff0c;“蒙特卡罗”这个名字是出自摩纳哥的蒙特卡罗赌场&#xff0c;这个方法是一类基于概率的方法的统称。是一种应用随机数来进行…

【ROS2】ROS2 构建系统 colcon 介绍、安装与使用

目录 一、ament 与 colcon二、colcon 模块化安装三、colcon 基本使用介绍3.1 常用命令构建工作空间清理构建结果构建特定的包指定构建系统并行构建扩展构建选项 3.2 其他命令列出所有可用的包忽略某些包查看colcon文档 一、ament 与 colcon ROS2采用了新的编译系统Ament&#…

Unity 2020、2021、2022、2023、6000下载安装

Unity 2020、2021、2022、2023、6000 下载安装 以Unity 6000.0.24fc1下载安装为例&#xff1a; 打开 https://unity.cn/ 优三缔 官方网站&#xff1b; 点击【产品列表】→点击【查看更多】→选择自己需要的版本→点【开始使用】 点击【从Unity Hub下载】 以Windows为例&am…

python自定义枚举类的试验与思考

一 现象 在python的3.4版本之前&#xff0c;是没有枚举类的。 所以&#xff0c;我自定义实现了一个enum类&#xff0c;目录如下&#xff1a; 代码如下&#xff1a; class enum(set):def __getattr__(self, name):if name in self:return nameraise AttributeErrorif __name_…

AIGC实践-使用Amazon Bedrock的SDXL模型进行文生图

一、Bedrock 简介 Amazon Bedrock 是 Amazon Web Services (AWS) 提供的一种生成式 AI 服务。通过 Bedrock&#xff0c;用户可以方便地使用多种基础模型&#xff08;Foundation Models&#xff09;&#xff0c;包括 OpenAI 的 GPT、Anthropic 的 Claude 等。这些模型可以用于各…

【MySQL】sql注入相关内容

【MySQL】sql注入相关内容 1. 为什么使用sql注入的时候&#xff0c;url传值的时候要使用–而不是– 使用–进行注释的时候需要在后面加一个空格才可以被认为是注释&#xff0c;url传值的过程中会将空格自动忽略&#xff0c;使用则可以在传输中保留为空格符号。&#xff08;同…

【YOLO】深入理解 CSP 瓶颈模块的变种:Bottleneck、C3、C3k、C2f 和 C3k2

深入理解 CSP 瓶颈模块的变种&#xff1a;Bottleneck、C3、C3k、C2f 和 C3k2 从 YOLOv3 到 YOLOv11&#xff0c;Ultralytics 团队结合当时的主流结构提出了各种适用于 YOLO 的模块&#xff0c;涵盖了不同的创新和优化思路&#xff0c;从而应对不断变化的目标检测需求。这些模块…

Redis中的数据结构详解

文章目录 Redis中的数据结构详解一、引言二、Redis 数据结构1、String&#xff08;字符串&#xff09;1.1、代码示例 2、List&#xff08;列表&#xff09;2.1、代码示例 3、Set&#xff08;集合&#xff09;3.1、代码示例 4、Hash&#xff08;散列&#xff09;4.1、代码示例 5…

计算机的错误计算(一百六十六)

摘要 探讨 MATLAB 关于算式 的计算误差。 例1. 已知 计算 直接贴图吧&#xff1a; 然而&#xff0c;16位的正确结果为 -0.9765626220703239e-21&#xff08;ISRealsoft 提供&#xff09;。这样&#xff0c;MATLAB输出的有效数字的错误率为 (16-2)/16 87.5% . 注&…

大模型时代的具身智能系列专题(十五)

Shubhangi Sinha团队 Shubhangi Sinha是康奈尔大学计算机科学系助理教授。在加入康奈尔大学之前&#xff0c;Tapo 是华盛顿大学计算机科学与工程专业的 NIH Ruth L. Kirschstein NRSA 博士后研究员。他在佐治亚理工学院获得了机器人学博士学位。他之前还曾在迪士尼研究中心工作…

【软件入门】Git快速入门

Git快速入门 文章目录 Git快速入门0.前言1.安装和配置2.新建版本库2.1.本地创建2.2.云端下载 3.版本管理3.1.添加和提交文件3.2.回退版本3.2.1.soft模式3.2.2.mixed模式3.2.3.hard模式3.2.4.使用场景 3.3.查看版本差异3.4.忽略文件 4.云端配置4.1.Github4.1.1.SSH配置4.1.2.关联…

鱼眼相机模型-MEI

参考文献&#xff1a; Single View Point Omnidirectional Camera Calibration from Planar Grids 1. 相机模型如下&#xff1a; // 相机坐标系下的点投影到畸变图像// 输入&#xff1a;相机坐标系点坐标cam 输出&#xff1a; 畸变图像素点坐标disPtvoid FisheyeCamAdapter::…