Linux-C语言 网络TCP单次通信、多次通信、多线程通信逐步实现

2023-05-16

一、TCP通信,只发送一次就结束程序

功能描述:

1、服务端一次只能连接一个客户端。
2、客户端只能向服务端发送一次消息,消息返回后客户端和服务器程序结束。
3、客户端向服务端发送一个字符串,服务端将字符串改为大写后返还到客户端。

步骤一:

依次编译客户端和服务器源程序,然后使用ifconfig命令查看虚拟机IP地址,用于之后客户端使用这个IP地址访问服务器。
在这里插入图片描述

步骤二:

打开两个终端,客户端服务器各一个,先运行服务器端,再运行客户端,全部运行之后便可以通过客户端向服务器发送消息了。
在这里插入图片描述

客户端源码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>

#define SERVPORT 8080

int main(int argc,int *argv[])
{
    int sockfd;
    int recv_len;
    struct sockaddr_in servaddr,cliaddr;
    char sendline[100];
    char recvline[100];

    if(argc != 2)
    {
        printf("need server address\n");
        exit(0);
    }

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    while(fgets(sendline,100,stdin) != NULL)
    {
        sendto(sockfd,sendline,strlen(sendline),0,
               (struct sockaddr *)&servaddr,sizeof(servaddr));

        recv_len = recvfrom(sockfd,recvline,100,0,NULL,NULL);

        recvline[recv_len] = '\0';

        fputs(recvline,stdout);

    }

    close(sockfd);

    return 0;
}

服务器源码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>

#include<ctype.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<fcntl.h>

#define SERVPORT 8080

int main(int argc)
{
    int listenfd,connfd,recv_len,send_len;
    socklen_t clilen;
    struct sockaddr_in servaddr,cliaddr;
    char buff[100];

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    printf("bind is sucessifully!\n");

    listen(listenfd,10);

    connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
    printf("connect sucessifully!\n");

    recv_len = recv(connfd,buff,100,0);

    buff[recv_len] = '\0';
    printf("received the following:\n");
    printf("%s",buff);

    for(int i=0; i<recv_len; i++)
    {
        buff[i] = toupper(buff[i]);
    }
    send_len = send(connfd,buff,recv_len,0);

    close(listenfd);
    return 0;
}

二、TCP通信,服务端与客户端实现多次通信

功能描述:

1、服务端一次只能连接一个客户端。
2、客户端可以向服务端多次发送消息,直到客户端发送一个空的消息后,客户端和服务器程序结束。
3、客户端向服务端发送一个字符串,服务端将字符串改为大写后返还到客户端。

步骤同第一个(省)

客户端源码:

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<unistd.h>
#define SERVPORT 8080

int main(int argc,char *argv[])
{
    int sockfd;
    int recv_len;
    struct sockaddr_in servaddr,cliaddr;
    char sendline[100];
    char recvline[100];

    if(argc != 2)
    {
        printf("need server address\n");
        exit(0);
    }

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    printf("send to service  :  ");
    while(fgets(sendline,100,stdin) != NULL)
    {
        send(sockfd,sendline,strlen(sendline),0);

        recv_len = recv(sockfd,recvline,100,0);

        recvline[recv_len] = '\0';
        printf("back from service:  ");
        fputs(recvline,stdout);
        printf("------------------------------\n");
        printf("send to service  :  ");
        //close(sockfd);
        //break;
    }

    close(sockfd);

    return 0;
}

服务器源码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>

#include<ctype.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<fcntl.h>

#define SERVPORT 8080

int main(int argc)
{
    int listenfd,connfd,recv_len,send_len;
    socklen_t clilen;
    struct sockaddr_in servaddr,cliaddr;
    char buff[100];

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    printf("bind is sucessifully! \n");

    listen(listenfd,10);
    printf("Waiting for clients to connect...\n");
    connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
    printf("%d connect sucessifully!\n",connfd);

    while(1)
    {
        recv_len = recv(connfd,buff,100,0);
        if(recv_len == 0)
        {
            break;
        }
        buff[recv_len] = '\0';
        printf("received the following:\n");
        printf("%s",buff);

        for(int i=0; i<recv_len; i++)
        {
            buff[i] = toupper(buff[i]);
        }
        send_len = send(connfd,buff,recv_len,0);
    }

    close(listenfd);
    return 0;
}

三、多线程实现TCP-Socket通信

功能描述:

1、服务端可以同时连接多个客户端。
2、多个客户端并发运行,同时实现与服务器的通信。
3、客户端向服务端发送一个字符串,服务端将字符串改为大写后返还到客户端。
4、客户端全部关闭时,服务器仍然运行,当有新的客户端连接时,继续工作。

步骤一:

依次编译客户端和服务器源程序,然后使用ifconfig命令查看虚拟机IP地址,用于之后客户端使用这个IP地址访问服务器。
在这里插入图片描述

步骤二:

然后打开三个终端,一个为服务器,两个为客户端,
在这里插入图片描述

步骤三:

照着下图,先运行服务器,再运行客户端,全部运行之后便可以通过客户端向服务器发送消息了。
在这里插入图片描述

效果展示:

在这里插入图片描述

客户端源码:

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

#define SERVPORT 8080

int main(int argc,char *argv[])
{
    int sockfd;
    int recv_len;
    struct sockaddr_in servaddr,cliaddr;
    char sendline[100];
    char recvline[100];

    if(argc != 2)
    {
        printf("need server address\n");
        exit(0);
    }

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    printf("send to service  :  ");
    while(fgets(sendline,100,stdin) != NULL)
    {
        send(sockfd,sendline,strlen(sendline),0);

        recv_len = recv(sockfd,recvline,100,0);

        recvline[recv_len] = '\0'; // 给接收到的结果加上字符串结束符
        printf("back from service:  ");
        fputs(recvline,stdout); //将收到的结果发送到控制台
        printf("------------------------------\n");
        printf("send to service  :  ");
        //close(sockfd);
        //break;
    }
    
    close(sockfd);
    return 0;
}

服务器源码

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>

#include<ctype.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<pthread.h>

#define SERVPORT 8080
#define CONNECTNUM 10
void thread_fun(void * cconnfd)
{
    int connfd =*(int *)cconnfd;
    int recv_len,send_len;
    char buff[100];
    
    while(1)
    {
        recv_len = recv(connfd,buff,100,0);
        if(recv_len == 0)
        {
            break;
        }
        buff[recv_len] = '\0';
        printf("received from client%d the following:\n",connfd);
        printf("%s",buff);


        for(int i=0; i<recv_len; i++)
        {
            buff[i] = toupper(buff[i]);
        }
        send_len = send(connfd,buff,recv_len,0);
        printf("have replied client%d ,over. \n ",connfd);
        printf("------------------------------ \n");
    }
    pthread_exit(NULL);
}
int main(int argc)
{
    int listenfd,connfd,recv_len,send_len;
    socklen_t clilen;
    struct sockaddr_in servaddr,cliaddr;
    char buff[100];
    pthread_t pid[CONNECTNUM];

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    printf("bind is sucessifully! \n");

    listen(listenfd,10);
    printf("Waiting for clients to connect...\n");

    for(int j =0; j<CONNECTNUM; j++)
    {
        connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
        printf("%d connect sucessifully!\n",connfd);
        pthread_create(&pid[j],NULL,(void *)thread_fun,&connfd);
    }

    close(listenfd);
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux-C语言 网络TCP单次通信、多次通信、多线程通信逐步实现 的相关文章

  • 前端面试题

    浏览器 输入一个URL到页面过程中发生了什么 xff08 高频 xff09 首先在浏览器中输入URL 查找缓存 xff1a 浏览器先查看浏览器缓存 系统缓存 路由缓存中是否有该地址页面 xff0c 如果有则显示页面内容 如果没有则进行下一步
  • MATALAB动态爱心代码

    第一步 xff1a 先下载MATLAB软件 xff08 该代码只适用于此软件 xff0c 要下载软件才可运行 xff09 第二步 xff1a 点击主页 新建脚本 xff08 可自己给脚本命名 xff0c 我命名的是aixin xff09 第
  • Linux相关博文中使用的头文件

    收录博文中看到的已经封装好的文件时 xff0c 方便各位查看 Log hpp 日志信息 pragma once include lt iostream gt include lt cstdio gt include lt cstdarg g
  • 构造函数和析构函数执行顺序

    析构函数运行顺序 xff1a 1 主函数结束 xff1b 2 函数调用结束 xff1b 3 用delete删除 xff08 new创建的 xff09 对象时 注释代码运行结果 输入坐标6 xff0c 3 xff0c 6 xff0c 2 xf
  • 27.【C/C++ 最全vector数组的用法 (详解)】

    vector动态数组 xff08 一 xff09 什么是vector xff1f xff08 二 xff09 vector的作用是什么 xff08 三 xff09 经典用法 1 vector函数的定义 代码展示 效果展示 2 vector的
  • 析构函数运行顺序

    全局变量 xff0c 静态局部变量 xff0c 局部变量空间的堆分配和栈分配 其中全局变量和静态局部变量时从 静态存储区中划分的空间 xff0c 二者的区别在于作用域的不同 xff0c 全局变量作用域大于静态局部变量 xff08 只用于声明
  • 03_临界段的保护

    一 临界段的概念 所谓的临界段就是在执行时不能被中断的代码段 在FreeRTOS中 xff0c 临界段最常出现的地方就是对全局变量的操作 那么什么情况下临界段会被打断 xff1f 一个是系统调度 xff0c 还有一个是外部中断 在FreeR
  • Qt自定义窗口继承基类

    设计一个窗口基类模板 xff0c 方便子类的统一风格使用 xff0c 省略重写事件函数 xff0c 代码思路
  • ROS学习笔记4:创建工作空间和功能包

    一 linux命令行使用基础 xff1a 1 cd命令 xff08 change directory xff09 xff1a xff08 1 xff09 语法 xff1a cd dirName xff08 dirName xff1a 要切换
  • 一段代码给你讲清楚【链式存储结构】

    1 基础定义 链式存储结构 xff08 linked storage structure xff09 xff0c 是逻辑存储结构的一种 xff0c 链式存储结构中每一个逻辑元素用一个内存结点存储 xff0c 每一个结点都是单独分配的 xff
  • Flask之before_request与after_request

    Flask之before request与after request 更多的用法或说明请查看文档 xff1a https dormousehole readthedocs io en latest api html flask Flask
  • C++教程之迭代器Iterator

    前言 之前的两篇文章我们主要了解了vector和string的相关知识 xff0c 从中我们知道可以通过下标来访问vector的元素或者string的字符 xff0c 但是除了这种方式还有一种更为通用的方式获取元素 xff0c 那就是迭代器
  • Qt 绘制图表 - Qt Charts版

    一 前言 自从 Qt 发布以来 xff0c 给广大跨平台界面研发人员带来了无数的福利 但是Qt自己却一直没有提供自带的图表库 xff0c 这就使得 QWT QCustomPlot 等第三方图表库有了巨大的生存空间 xff0c 为了降低开发成
  • Qt 多线程使用moveToThread

    Qt有两种多线程的方法 xff0c 其中一种是继承QThread的run函数 xff0c 另外一种是把一个继承于QObject的类用moveToThread函数转移到一个Thread里 Qt4 8之前都是使用继承QThread的run这种方
  • Qt 之http学习

    在Qt网络编程中 xff0c 需要用到协议 xff0c 即HTTP 它是超文本传输协议 xff0c 它是一种文件传输协议 新建工程名为 http xff0c 然后选中QtNetwork模块 xff0c 最后Base class选择QWidg
  • QT之QString

    字符串类 QString xff1a 在Qt官方文档中是这样描述QString的 xff1a The QString class provides a Unicode character string 我们可以将做C 43 43 中的str
  • 什么是栈?什么是任务栈?

    在裸机系统中 xff0c 它们统统放在一个叫栈的地方 栈式单片机RAM里一段连续的内存空间 栈的大小一般在启动文件或者链接脚本里里面指定 最后由C库函数 main进行初始化 每个任务都是独立的 xff0c 互不干扰的 所以要为每个任务都分配
  • OPENMV上的目标检测,目标定位模型

    目标板定位模型 代码地址 前言 在17届省赛结束后 xff0c 因为担心国赛场地光照影响较大 xff0c 写了这个目标检测算法 但因为时间以及实力不足 xff0c 算法仅有了个雏形 xff0c 没能成功部署 xff0c 非常遗憾 今年寒假终
  • select函数当对端关闭后的状态

    struct timeval timeout 61 5 0 rset 61 allset nready 61 select maxfd 43 1 amp rset NULL NULL amp timeout 当使用select等待客户端发送
  • web渗透之攻击 Authentication-1-

    可利用常见漏洞 认证http明文传输 xff0c 未加密 xff0c 攻击者可通过中间人攻击获取默认密码弱口令 xff0c 简单的credentials xff0c 可以通过暴力破解获取通过其他漏洞绕过认证不正确的重置密码功能密码在本地存储

随机推荐

  • UART——学习总结

    UART 一 含义 xff1a 通用异步收发传输器 xff08 Universal Asynchronous Receiver Transmitter xff0c 通常称作UART xff09 是一种串行异步收发协议 xff0c 二 工作原
  • 海康威视web3.0+vue项目使用(踩坑之路)ps:附webVideoCtrl.js文件

    文章目录 1 海康威视web3 02 vue项目应用3 运行环境 最近公司开发了一版监控视频的vue项目 我作为实现需求的前端真的是难为我了 各种调查后知道海康威视有web开发包 跟海康威视的SDK联系后发给我两个web二次开发包 CH W
  • GB28181国标平台软件(包含服务器和客户端)

    GB28181是国家针对安防领域制定的一个通信协议标准 xff0c 目的是解决不同平台 不同设备间通信协议不统一的问题 GB28181标准从2011制定的第一个版本开始 xff0c 到最近的2016版本 xff0c 制定的协议内容越来越细
  • 国标服务器GBServerPlatform对接海康NVR的操作说明

    这一篇文章介绍QuickGBLink开发的国标服务器如何对接海康NVR xff08 网络硬盘录像机 xff09 xff0c 主要讲解相关的操作步骤 xff08 GBT28181平台软件下载地址 xff1a https github com
  • 国标服务器GBServerPlatform对接海康摄像头的操作说明

    这篇文章讲解一下QuickGBLink开发的国标服务器如何对接海康IPC xff08 GBT28181国标平台软件下载地址 xff1a https github com QuickGBLink88 GB28181 ServerPlatfor
  • 开源工具:ONVIF协议实现搜索局域网摄像机(IPC)+RTSP地址获取

    Onvif协议做安防监控的人应该都很熟悉 xff0c 它广泛被用在各种安防设备中 xff0c 比如IPC DVR NVR 在局域网中发现IPC设备很多就是基于Onvif协议实现的 本文章给大家介绍QuickGBLink开源的一个工具 xff
  • 开源C++ RTSP客户端(支持RTP Over TCP)

    QuickGBLink开源的这个RTSP客户端是用C 43 43 写的 xff0c 目前仅实现了RTP Over TCP传输 支持接收多种视音频格式的流 xff0c 视频格式支持MPEG4 H264 H265 xff0c 音频格式支持AAC
  • 开源工具:实现用FFmpeg接收RTSP/RTMP/HLS流和录制文件

    上一篇文章介绍了QuickGBLink开发的一个RTSP客户端 开源C 43 43 RTSP客户端 xff0c 实现了通过TCP接收RTP流的功能 xff0c 但是在局域网监控中 xff0c 很多时候RTSP服务器和客户端都是用UDP模式来
  • 国标PS流打包和RTP发送代码

    这个国标PS流打包 封包的代码来自于互联网 xff0c QuickGBLink在原先代码基础上做了一些改进 因为代码来自于别人的成果 xff0c 基于互联网知识分享的精神 xff0c 我们打算将其开源 xff0c 希望能对更多学习和开发国标
  • 国标PS流解包(解封装)代码

    该代码最初的版本来自于互联网 xff0c 首先感谢前辈无私分享的精神 xff0c 这个PS流解析代码小巧和可读性好 xff0c 是学习PS格式的一个很好的参考例子 但原来的代码有不少Bug xff0c QuickGBLink在原先代码基础上
  • 错误./hello: error while loading shared libraries: libQtGui.so.4: cannot open shared object file:

    之前一直想在ARM 上跑qt xff0c 但都出现错误 xff1a hello error while loading shared libraries libQtGui so 4 cannot open shared object fil
  • linux eth0设置

    命令行设定IP地址 ifconfig eth0 192 168 1 12 将eth0IP设置为192 168 1 12 ifconfig eth0 up 使eth0使能 如果开发板与路由器连接 xff0c 并且路由器能够自动分配IP地址 x
  • printk打印不能显示到终端的解决方法

    printk与printf有个不同的地方 xff0c 就是printk有打印级别 使用printk时 xff0c Linux内核根据日志级别 xff0c 可能把消息打印到当前控制台上 xff0c 这个控制台是一个字符设备 这些消息从终端输出
  • qt socket通信中接收client发送是十六进制数据包

    在QT的服务端接收客户端发送的十六进制收据包 xff0c 经转换后显示在LineEdit上 xff0c 并把接收到的数据包转化为char 类型 xff0c 为后期数据处理做准备 recbuf在头文件类中一定义 xff1a QByteArra
  • 两个双口ram之间数据的传递

    1 如果两个双口ram数据位宽相同 xff0c 则采用时钟快的ram等待时钟慢的ram来完成从一个ram中读取数据并存储到另一个ram中 xff1b 例如从ram A中读取数据到ram xff22 中 xff0c xff52 xff41 x
  • + - 与>> <<运算优先级

    43 运算符的优先级高于 lt lt gt gt 位移运算符 span class hljs keyword int span mian span class hljs keyword int span a 61 span class hl
  • linux col 过滤控制字符

    参考http blog 51cto com jim123 1833502 使用过Unix系统的人肯定会知道man帮助的功能强大 xff0c 是官方的帮助文档 xff0c 我们平时可以通过它来查询不知道如何使用的命令或者查询linux的系统C
  • gcc 参数

    gcc gcc与 g 43 43 分别是GNU的C与 C 43 43 的编译器 xff0c 在编译工作中分4步 xff1a 1 预处理 xff0c 生成 i文件 2 编译器 xff0c 编译后停下来 xff0c 生成 o的目标文件 3 汇编
  • gdb 调试

    原文http linuxtools rst readthedocs io zh CN latest tool gdb html span class hljs variable span span class hljs number 1 s
  • Linux-C语言 网络TCP单次通信、多次通信、多线程通信逐步实现

    一 TCP通信 xff0c 只发送一次就结束程序 功能描述 xff1a 1 服务端一次只能连接一个客户端 2 客户端只能向服务端发送一次消息 xff0c 消息返回后客户端和服务器程序结束 3 客户端向服务端发送一个字符串 xff0c 服务端