TCP实现局域网通信

2023-05-16

TCP实现局域网通信

TCP客户端通信步骤:
1:创建套接字 sockfd = socket(AF_INET ,SOCK_STREAM ,0);
2:填写服务器结构体信息

 struct sockaddr_in serveraddr;
socklen_t addrlen = sizeof(serveraddr);
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));

其中服务器信息结构体要用sockaddr_in创建
3:发送客户端连接请求

connect(sockfd, (struct sockaddr *)&serveraddr,addrlen);

注意服务器信息结构体要进行强制类型转换
4:进行通信

recv(sockfd, buf1, 128, 0);
send(sockfd, buf, 128, 0);
注意send和recv可以设置阻塞和非阻塞 recv默认阻塞

其中可以通过创建进程和线程实现接收和发送
5:关闭套接字
TCP服务器通信步骤:
1:创建套接字

sockfd = socket(AF_INET, SOCK_STREAM, 0)

2:将套接字和服务器信息结构体绑定

struct sockaddr_in serveraddr, clientaddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
bind(sockfd, (struct sockaddr *)&serveraddr, addrlen)

3:将套接字设置为监听状态

listen(sockfd, 5)

4:阻塞等待客户端连接请求

acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)

5:进行通信
6:关闭套接字
关闭监听套接字导致服务器无法建立新连接,但不影响已建立连接
关闭accept返回的套接字代表该套接字的连接关闭,不影响服务器监听
实现TCP并发服务器
客户端代码:client_Ancy.c

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr

z
	char buf1[128] = "";
        pthread_t thread;
	int sockfd;
	char ip[] = "180.201.00.00";
	char port[] = "8080";
void thread_do(){
while(1){

	fgets(buf,128,stdin);
	buf[strlen(buf) - 1] = '\0';
	
	send(sockfd, buf, 128, 0);

}
}
int main(int argc, char const *argv[])
{
	if (argc<3){
        printf("Usage: %s [ip] [port]\n", argv[0]);
        exit(1);
	}

	sockfd = socket(AF_INET ,SOCK_STREAM ,0);
	
	
         struct sockaddr_in serveraddr;
        socklen_t addrlen = sizeof(serveraddr);
        
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
        serveraddr.sin_port = htons(atoi(argv[2]));
        //serveraddr.sin_addr.s_addr = inet_addr(ip);
        //serveraddr.sin_port = htons(atoi(port));

	
	connect(sockfd, (struct sockaddr *)&serveraddr,addrlen);
	
	pthread_create(&thread, NULL, (void *)&thread_do,NULL);//此时可以通过把thread_do设置为指针函数,即定义时void * thread_do()参数可以写thread_do
	
while(1){
	memset(buf1,0,128);
	recv(sockfd, buf1, 128, 0);
	printf("recv:%s\n",buf1);
	}
	close(sockfd);

}

多进程实现服务器代码:server_Ancy.c

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

//使用多进程实现TCP并发服务器

#define N 128
#define ERR_LOG(errmsg) do{\
                            perror(errmsg);\
                            exit(1);\
                        }while(0)

void handler(int sig)
{
    wait(NULL);
}

int main(int argc, char const *argv[])
{
    if(argc < 3)
    {
        fprintf(stderr, "Usage: %s <server_ip> <server_port>\n", argv[0]);
        exit(1);
    }    

    int sockfd, acceptfd;
    struct sockaddr_in serveraddr, clientaddr;
    socklen_t addrlen = sizeof(serveraddr);

    //第一步:创建套接字
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        ERR_LOG("fail to socket");
    }

    //将套接字设置为允许重复使用本机地址或者为设置为端口复用
    int on = 1;
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    {
        ERR_LOG("fail to setsockopt");
    }

    //第二步:填充服务器网络信息结构体
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    //第三步:将套接字与服务器网络信息结构体绑定
    if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0)
    {
        ERR_LOG("fail to bind");
    }

    //第四步:将套接字设置为被动监听状态
    if(listen(sockfd, 5) < 0)
    {
        ERR_LOG("fail to listen");
    }

    //使用型号,异步的方式处理僵尸进程
    signal(SIGCHLD, handler);

    while(1)
    {
        //第五步:阻塞等待客户端的连接请求
        if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
        {
            ERR_LOG("fail to accept");
        }

        //打印客户端的信息
        printf("%s -- %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

        //使用fork函数创建子进程,父进程继续负责连接,子进程负责与客户端通信
        pid_t pid;
        if((pid = fork()) < 0)
        {
            ERR_LOG("fail to fork");
        }
        else if(pid > 0) //父进程负责执行accept,所以if语句结束后继续在accept函数的位置阻塞
        {
        }
        else //子进程负责跟指定的客户端通信
        {
            char buf[N] = "";
            ssize_t bytes;
            while (1)
            {
                if((bytes = recv(acceptfd, buf, N, 0)) < 0)
                {
                    ERR_LOG("fail to recv");
                }
                else if(bytes == 0)
                {
                    printf("The client quited\n");
                    exit(0);
                }

                if(strncmp(buf, "quit", 4) == 0)
                {
                    exit(0);
                }

                printf("from client: %s\n", buf);

                strcat(buf, " ^_^");
                if(send(acceptfd, buf, N, 0) < 0)
                {
                    ERR_LOG("fail to send");
                }
            }
        }
    }

    return 0;
}

多线程实现服务器代码:server_Ancy.c

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

#define N 128
#define ERR_LOG(errmsg) do{\
                            perror(errmsg);\
                            exit(1);\
                        }while(0)

typedef struct{
    struct sockaddr_in addr;
    int acceptfd;
}MSG;

void *pthread_fun(void *arg)
{
    char buf[N] = "";
    ssize_t bytes;
    MSG msg = *(MSG *)arg;
    while (1)
    {
        if((bytes = recv(msg.acceptfd, buf, N, 0)) < 0)
        {
            ERR_LOG("fail to recv");
        }
        else if(bytes == 0)
        {
            printf("The client quited\n");
            pthread_exit(NULL);
        }

        if(strncmp(buf, "quit", 4) == 0)
        {
            printf("The client quited\n");
            pthread_exit(NULL);
        }

        printf("[%s - %d]: %s\n", inet_ntoa(msg.addr.sin_addr), ntohs(msg.addr.sin_port), buf);

        strcat(buf, " ^_^");
        if(send(msg.acceptfd, buf, N, 0) < 0)
        {
            ERR_LOG("fail to send");
        }
    }
}

int main(int argc, char const *argv[])
{
    if(argc < 3)
    {
        fprintf(stderr, "Usage: %s <server_ip> <server_port>\n", argv[0]);
        exit(1);
    }    

    int sockfd, acceptfd;
    struct sockaddr_in serveraddr, clientaddr;
    socklen_t addrlen = sizeof(serveraddr);

    //第一步:创建套接字
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        ERR_LOG("fail to socket");
    }

    //将套接字设置为允许重复使用本机地址或者为设置为端口复用
    int on = 1;
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    {
        ERR_LOG("fail to setsockopt");
    }

    //第二步:填充服务器网络信息结构体
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    //第三步:将套接字与服务器网络信息结构体绑定
    if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0)
    {
        ERR_LOG("fail to bind");
    }

    //第四步:将套接字设置为被动监听状态
    if(listen(sockfd, 5) < 0)
    {
        ERR_LOG("fail to listen");
    }

    while(1)
    {
        //第五步:阻塞等待客户端的连接请求
        if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
        {
            ERR_LOG("fail to accept");
        }

        //打印客户端的信息
        //printf("%s -- %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

        //创建子线程与客户端进行通信
        MSG msg;
        msg.addr = clientaddr;
        msg.acceptfd = acceptfd;
        pthread_t thread;
        if(pthread_create(&thread, NULL, pthread_fun, &msg) != 0)
        {
            ERR_LOG("fail to pthread_create");
        }
        pthread_detach(thread);
    }

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

TCP实现局域网通信 的相关文章

  • 什么是子网掩码,如何判断两个IP是不是同一网段

    1 xff1a 什么是子网掩码 xff1f 子网掩码不能单独存在 xff0c 它必须结合IP地址一起使用 子网掩码只有一个作用 xff0c 就是将某个IP地址划分成网络地址和主机地址两部分 说的通俗的话 xff0c 就是用来分割子网和区分那
  • 利用esp-8266实现wifi攻击

    0x00 前言 之前在b站上看到这个wifi模块的攻击视频感觉挺有意思 xff0c 就在某宝上入了一个拿回来玩玩 0x01 外观 转接头需要自己另外买 0x03 编译程序 https anky cc esp8266 deauther wif
  • 如何从 JavaScript 对象中删除属性?

    问题描述 xff1a 给定一个对象 xff1a let myObject span class token operator 61 span span class token punctuation span span class toke
  • 在 Git 中推送提交时消息“src refspec master does not match any”

    问 xff1a 我克隆我的存储库 xff1a git clone ssh span class token operator span span class token operator span span class token oper
  • Qt编译、链接和运行参数的设置

    Qt编译 链接和运行参数的设置 Qt笔记 使用 Qt Creator 集成开发环境构建和运行程序是一件非常简单的事情 xff0c 一个按钮或者一个快捷键搞定全部 xff0c 通过 Qt Creator使用教程 xff08 简明版 xff09
  • 常用Linux命令行技巧

    结果以表格形式输出 column t 比如 xff1b span class token function mount span span class token operator span column t 默认分隔符为空格 xff0c
  • CV往哪卷?李飞飞指出三颗「北极星」:具身智能,视觉推理和场景理解

    点击下方卡片 xff0c 关注 CVer 公众号 AI CV重磅干货 xff0c 第一时间送达 转载自 xff1a 新智元 编辑 xff1a LRS 导读 ImageNet见证了计算机视觉发展的辉煌历程 xff0c 在部分任务性能已超越人类
  • Java异常处理的九个最佳实践

    1 确保在Finally程序块中完成资源释放或者使用Try With语句 比如对于InputStream xff0c 当我们使用完毕 xff0c 我们要确保资源被正确关闭 xff0c 比如下面我们常见的错误用法 xff0c 不要在try模块
  • CodeMirror使用笔记

    最近因工作需要 xff0c 在项目中使用了CodeMirror代码编辑器 xff0c 以下是使用笔记 首先 xff0c 看下最终的效果 引入基本的需要资源 lt script src 61 34 lt 61 request getConte
  • JAVA注解

    Java注解Annotations主要用于为目标程序提供额外补充的说明信息 注解以 64 符号标识注解并不改变编译程序的行为注意可以为程序元素 xff1a 实例变量 构造方法 方法或者类添加元数据信息注解并不是单纯的注释 xff0c 但却可
  • ubuntu中GitLab的安装与配置

    这里 xff0c 我们采用离线安装的方式安装GitLab 首先 xff0c 我们从清华大学开源软件镜像站中下载软件包 xff0c 用户可根据实际的服务器操作系统版本来选择不同的镜像资源 xff0c 这里我们以ubuntu为例 执行命令sud
  • Jenkins使用笔记

    本章简单记录Jenkins的使用笔记 首先 xff0c 我们从官网中下载安装介质 xff0c 可以看到这里有适合各种操作系统版本的安装源介质 xff0c 简单起见 xff0c 我们直接下载一个通用的war程序包 执行命令java jar j
  • GitLab 与 Jenkins 持续集成实践

    首先 xff0c 我们简单说明下我们的部署环境 xff1a GitLab xff1a 192 168 43 61 Jenkins xff1a 192 168 43 116 Jenkins中系统设置中 xff0c 配置GitLab连接信息 x
  • Linux下免密认证登录失败原因总结

    事件背景 A机器已经生产rsa密钥且已经将public key添加到B机器 root ssh authorized keys xff0c 但是从A机器上ssh root 64 B机器时仍然需要输入密码 xff0c 即无密码认证失败 原因总结
  • 公钥添加到authorized_keys到文件中之后仍无法免密登陆

    接上一章 xff0c 关于Linux下免密登陆失败 xff0c 这里找了Stackoverflow上关于这个问题的讨论 xff1a Adding public key to ssh authorized keys does not log
  • Java 8 中的List排序

    按字母顺序排序字符串列表 List lt String gt cities 61 Arrays asList 34 Milan 34 34 london 34 34 San Francisco 34 34 Tokyo 34 34 New D
  • Microservices vs SOA - 微服务与SOA

    开始之前 xff0c 我们先简单看下单体架构 SOA与微服务之间的区别 xff0c 如下图所示 xff1a 简单来讲 xff0c 对于单体架构 xff0c 其就像一个超大容器 xff0c 容器内集中包含了该应用的所有软件组件 xff0c 并
  • Python 机器学习8:sklearn 聚类算法

    1 K Means算法是一种广泛使用的聚类算法 from sklearn cluster import KMeans K Means是聚焦于相似的无监督的算法 xff0c 以距离作为数据对象间相似性度量的标准 xff0c 即数据对象间的距离
  • 什么是微服务——微服务架构体系介绍

    Why Microservices 回答这个问题前 xff0c 我们先看下之前大行其道的单体架构 Monolithic Architecture xff0c 对于非专业人士来讲 xff0c 所谓的单体架构 xff0c 其就像一个超大容器 x
  • 微服务架构特征

    一个典型的微服务架构 xff08 MSA xff09 通常包含以下组件 xff1a 客户端 xff1a 微服务架构着眼于识别各种不同的类型的设备 xff0c 以及在此设备上进行的各种管理操作 xff1a 搜索 构建 配置等等身份标识提供者

随机推荐

  • 微服务架构系列——API服务网关

    本章我们简单介绍微服务架构下的API服务网关 xff0c 本章我们将讨论以下话题 xff1a 什么是API服务网关为什么需要API服务网关API服务网关的工作机制 处理横切关注点 当我们在开发设计大型软件应用时 xff0c 我们一般都会采用
  • Java之keytool命令学习

    Java Keytool is a key and certificate management utility It allows users to manage their own public private key pairs an
  • HashMap 与 HashTable的区别

    HashMap 实现了Map接口非线程同步 xff0c 非线程安全不允许重复键键和值均允许为null HashMap lt Interger String gt employeeHashmap 61 new HashMap lt Integ
  • 如何避免敏捷失败?

    很多人都听说敏捷 xff0c 有些人知道敏捷是什么 xff0c 有些人也尝试过敏捷 xff0c 本章中将列举出一些常见的错误敏捷实践 xff0c 如果想要避免敏捷失败 xff0c 建议还是要对照下你所在的敏捷团队中有没有类似的敏捷实践 xf
  • 一个人有文化,到底有多重要?

    关于什么是文化 xff0c 我最最欣赏的回答 xff0c 是作家梁晓声的四句概括 xff1a 根植于内心的修养 xff0c 无需提醒的自觉 xff0c 以约束为前提的自由 xff0c 为别人着想的善良 01 一位叫做 Judy 的空姐 xf
  • MyBatis动态SQL中Map参数处理

    在MyBatis中 xff0c 如果我们需要传递两个参数 xff0c 有一种方式是通过Map作为传入参数 xff0c 在动态SQL中 xff0c 我们需要对传入的Map参数中的值进行判断 xff0c 然后进行动态SQL的条件拼接处理 假设我
  • MyBatis框架下防止SQL注入

    与传统的ORM框架不同 xff0c MyBatis使用XML描述符将对象映射到SQL语句或者存储过程中 xff0c 这种机制可以让我们更大的灵活度通过SQL来操作数据库对象 xff0c 因此 xff0c 我们必须小心这种便利下SQL注入的可
  • 使用android 视频解码mediaCodec碰到的几个问题

    问题1 mediaCodec dequeueInputBuffer一直返回 1 xff0c APP现象 xff1a 视屏卡屏 原因 xff1a 这是因为inputbuffer的内容有误 xff0c 导致无法解码 可通过设延时时间解决 xff
  • 云计算思维导图

    根据近期的云计算学习心得 xff0c 将云计算部分内容制作成思维导图 xff0c 方便于广大云计算学习者作为辅导讲义 xff01 思维导图内容主要包含 xff1a 1 云计算概述 2 云体系结构 3 网络资源 4 存储资源 5 硬件介绍 6
  • 路由器重温——串行链路链路层协议积累

    对于广域网接口来说 xff0c 主要的不同或者说主要的复杂性在于理解不同接口的物理特性以及链路层协议 xff0c 再上层基本都是 IP 协议 xff0c 基本上都是相同的 WAN口中的serial接口主要使用点对点的链路层协议有 xff0c
  • 路由器重温——PPPoE配置管理-2

    四 配置设备作为PPPoE服务器 路由器的PPPoE服务器功能可以配置在物理以太网接口或 PON 接口上 xff0c 也可配置在由 ADSL 接口生成的虚拟以太网接口上 1 配置虚拟模板接口 虚拟模板接口VT和以太网接口或PON接口绑定后
  • Python入门自学进阶——1--装饰器

    理解装饰器 xff0c 先要理解函数和高阶函数 首先要明白 xff0c 函数名就是一个变量 xff0c 如下图 xff0c 定义一个变量名和定义一个函数 xff0c 函数名与变量名是等价的 既然函数名就是一个变量名 xff0c 那么在定义函
  • Python入门自学进阶-Web框架——21、DjangoAdmin项目应用

    客户关系管理 以admin项目为基础 xff0c 扩展自己的项目 一 创建项目 二 配置数据库 xff0c 使用mysql数据库 xff1a 需要安全mysqlclient模块 xff1a pip install mysqlclient D
  • Python入门自学进阶-Web框架——33、瀑布流布局与组合查询

    一 瀑布流 xff0c 是指页面布局中 xff0c 在显示很多图片时 xff0c 图片及文字大小不相同 xff0c 导致页面排版不美观 如上图 xff0c 右边的布局 xff0c 因为第一行第一张图片过长 xff0c 第二行的第一张被挤到第
  • Python入门自学进阶-Web框架——34、富文本编辑器KindEditor、爬虫初步

    KindEditor 是一个轻量级的富文本编辑器 xff0c 应用于浏览器客户端 一 首先是下载 xff1a http kindeditor net down php xff0c 如下图 下载后是 解压缩后 xff1a 红框选中的都可以删除
  • Python入门自学进阶-Web框架——35、网络爬虫使用

    自动从网上抓取信息 xff0c 就是获取相应的网页 xff0c 对网页内容进行抽取整理 xff0c 获取有用的信息 xff0c 保存下来 要实现网上爬取信息 xff0c 关键是模拟浏览器动作 xff0c 实现自动向网址发送请求 xff0c
  • 6、spring的五种类型通知

    spring共提供了五种类型的通知 xff1a 通知类型接口描述Around 环绕通知org aopalliance intercept MethodInterceptor拦截对目标方法调用Before 前置通知org springfram
  • 路由器接口配置与管理——1

    路由器的接口相对于交换机来说最大的特点就是接口类型和配置更为复杂 xff0c 一般吧路由器上的接口分为三大类 xff1a 一类用于局域网的LAN接口 xff0c 一类用于广域网接入 互联的WAN接口 xff0c 最后一类可以应用于LAN组网
  • 路由配置与管理——静态路由配置与管理

    静态路由是一种最简单的路由 xff0c 需手工配置 xff0c 用一条指令指定静态路由的目的IP地址 子网掩码 下一跳IP地址 xff0c 或者出接口 优先级等主要参数值就可以了 还可根据实际需要配置静态路由与BFD或者NQA的联动 一 路
  • TCP实现局域网通信

    TCP实现局域网通信 TCP客户端通信步骤 xff1a 1 xff1a 创建套接字 sockfd 61 socket AF INET SOCK STREAM 0 2 xff1a 填写服务器结构体信息 span class token key