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

news2025/7/5 9:43:29

目录

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

成功截图

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

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

相关文章

物体网格弹性变形---Unity中实现

在游戏引擎场景中的3D物体是由一定数量的点、面组成的&#xff0c;如下图&#xff1a; 要使这些物体变形就是改变3D物体每个顶点状态。 1.首先在Unity场景中增加一个球体&#xff0c;如下图 3D组件默认拥有MeshFilter、meshRenderer、Collider组件&#xff0c;分别用来获取Mes…

【ArcGISPro】根据yaml构建原始Pro的conda环境

使用场景 我们不小心把原始arcgispro-py3的conda环境破坏了,我们就可以使用以下方法进行修复 查找文件 在arcgis目录下找到yaml文件 如果没找到请复制以下内容到新的yaml文件 channels: - esri - defaults dependencies: - anyio=4.2.0=py311haa95532_0 - appdirs=1.4.4=p…

【Y20030007】基于java+servlet+mysql的垃圾分类网站的设计与实现(附源码 配置 文档)

网垃圾分类网站的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着全球环境保护意识的提升&#xff0c;垃圾分类已成为一项紧迫且重要的任务。为了有效推动垃圾分类的实施&#xff0c;提升公众的环保意识和参与度&#xff0c;垃圾分类已…

【Python爬虫五十个小案例】爬取豆瓣电影Top250

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1fab2;前言 在这篇博客中&#xff0c;我们将学习如何使用Python爬取豆瓣电影Top250的数据。我们将使用requests库来发送HTTP请求&#xff0c;…

C++ 优先算法 —— 长度最小的子数组(滑动窗口)

目录 题目&#xff1a;长度最小的子数组 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口&#xff08;同向双指针&#xff09; 滑动窗口正确性 3. 代码实现 Ⅰ. 暴力枚举(会超时&#xff09; Ⅱ. 滑动窗口&#xff08;同向双指针&#xff09; 题目&#xff1a;长…

C++设计模式——Singleton单例模式

一、单例模式的定义 单例模式&#xff0c;英文全称Singleton Pattern&#xff0c;是一种创建型设计模式&#xff0c;它保证一个类在程序中仅有一个实例&#xff0c;并对外提供一个访问的该类实例的全局接口。 单例模式通常用于需要控制对象资源的开发场景&#xff0c;一个类…

【Linux系统】—— 基本指令(三)

【Linux系统】—— 基本指令&#xff08;三&#xff09; 1 一切皆文件2 重定向操作2.1 初始重定向2.2 重定向的妙用2.3 追加重定向2.4 输入重定向2.5 一切皆文件与重定向结合 3 Linux 中的文件类型4 日志5 「more」命令6 「less」命令7 「head」与「tail」7.1 查看文件开头和结…

探索 Python 任务自动化的新境界:Invoke 库揭秘

文章目录 探索 Python 任务自动化的新境界&#xff1a;Invoke 库揭秘背景&#xff1a;为何选择 Invoke&#xff1f;什么是 Invoke&#xff1f;如何安装 Invoke&#xff1f;5个简单的库函数使用方法1. 定义任务2. 带参数的任务3. 运行 Shell 命令4. 任务参数化5. 列出任务 场景应…

【C++】list模拟实现(详解)

本篇来详细说一下list的模拟实现&#xff0c;list的大体框架实现会比较简单&#xff0c;难的是list的iterator的实现。我们模拟实现的是带哨兵位头结点的list。 1.准备工作 为了不和C库里面的list冲突&#xff0c;我们在实现的时候用命名空间隔开。 //list.h #pragma once #…

shell脚本(6)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;shell(6)if条件判断与for循环结构_哔哩哔哩_bilibili 本文主要讲解shell脚本中的if条件判断和for循环结构。 一、if语句 Shell 脚本中的 if 语句…

JavaScript基础 document.write()方法

JavaScript基础 document.write方法 1.简单认识document.write()2.document.write() 的使用 1.简单认识document.write() document.write() 是一种 JavaScript 方法&#xff0c;用于将内容直接写入到 HTML 文档中。它可以用来动态地在页面加载时插入文本、HTML 代码、图片等内…

Linux笔记---进程:进程切换与O(1)调度算法

1. 补充概念 1.1 并行与并发 竞争性&#xff1a;系统进程数目众多&#xff0c;而CPU资源只有少量&#xff0c;甚至只有1个&#xff0c;所以进程之间是具有竞争属性的。为了高效完成任务&#xff0c;更合理竞争相关资源&#xff0c;便具有了优先级。独立性&#xff1a;多进程运…

使用ENSP实现浮动静态路由

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable 进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为1.1.1.1/24 ip address 1.1.1.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为2.…

GoF设计模式——结构型设计模式分析与应用

文章目录 UML图的结构主要表现为&#xff1a;继承&#xff08;抽象&#xff09;、关联 、组合或聚合 的三种关系。1. 继承&#xff08;抽象&#xff0c;泛化关系&#xff09;2. 关联3. 组合/聚合各种可能的配合&#xff1a;1. 关联后抽象2. 关联的集合3. 组合接口4. 递归聚合接…

【论文复现】深度知识追踪

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ 深度知识追踪 1. 论文概述2. 论文方法3. 实验部分3.1 数据集3.2 实验步骤3.3 实验结果 4 关键代码 1. 论文概述 知识追踪的任务是对学生的知…

Linux: 进程地址空间(理解虚拟地址和页表)

目录 1. 虚拟地址 2. 进程地址空间分布 3. 描述进程地址空间 4. 内存管理——页表 5. 父子进程的虚拟地址关系 6. 页表标记位 6.1 读写权限 6.2 命中权限 7.为什么存在进程地址空间 1. 虚拟地址 #include <stdio.h> #include <unistd.h> #include <sy…

C语言:深入理解指针

一.内存和地址 我们知道计算机上CPU&#xff08;中央处理器&#xff09;在处理数据的时候&#xff0c;需要的数据是在内存中读取的&#xff0c;处理后的数据也会放回内存中&#xff0c;那我们买电脑的时候&#xff0c;电脑上内存是 8GB/16GB/32GB 等&#xff0c;那这些内存空间…

transformer.js(一):这个前端大模型运行框架的可运行环境、使用方式、代码示例以及适合与不适合的场景

随着大模型的广泛应用&#xff0c;越来越多的开发者希望在前端直接运行机器学习模型&#xff0c;从而减少对后端的依赖&#xff0c;并提升用户体验。Transformer.js 是一个专为前端环境设计的框架&#xff0c;它支持运行基于 Transformer 架构的深度学习模型&#xff0c;尤其是…

uni-app 发布媒介功能(自由选择媒介类型的内容) 设计

1.首先明确需求 我想做一个可以选择媒介的内容&#xff0c;来进行发布媒介的功能 &#xff08;媒介包含&#xff1a;图片、文本、视频&#xff09; 2.原型设计 发布-编辑界面 通过点击下方的加号&#xff0c;可以自由选择添加的媒介类型 但是因为预览中无法看到视频的效果&…

行业分析---2024年小鹏汽车AI Day及三季度财报

1 背景 在之前的博客中&#xff0c;笔者撰写了多篇行业类分析的文章&#xff08;科技新能源&#xff09;&#xff1a; 《行业分析---我眼中的Apple Inc.》 《行业分析---马斯克的Tesla》 《行业分析---造车新势力之蔚来汽车》 《行业分析---造车新势力之小鹏汽车》 《行业分析-…