008.一个简单的网络服务器开发----回声服务器

简介: 简单的回声服务器实现项目需求 实现回声服务器的客户端/服务器程序,客户端通过网络连接到服务器,并发送任意一串英文信息,服务器端接收信息后,将每个字符转换为大写并回送给客户端显示。

简单的回声服务器实现

项目需求

       实现回声服务器的客户端/服务器程序,客户端通过网络连接到服务器,并发送任意一串英文信息,服务器端接收信息后,将每个字符转换为大写并回送给客户端显示。

技术分析

1.网络字节序

2.sockaddr数据结构

3.ip地址转换函数

4.socket函数

5.bind函数

6.listen函数

7.accept函数

8.connect函数

9.write函数

10.read函数


   网络通信与socket,这一部分博主以前做过详细的分析所以直接附上以前的博客链接了:以下链接均为作者--socket编程专栏文章。

博主相关的技术博客


  • 网络编程之 socket编程

网络编程函数小总结与初识socket

网络编程之bind()的未解之谜

网络编程之 字节序和深入理解bind()函数

网络编程之 listen()函数的使用与三次握手的理解

socket编程之 accept函数的理解

socket编程之 connect()函数

基于 Linux 的文件操作 网络编程的最后一环


 其实呢,你去看博主的网络编程专栏会发现就这这几天博主其实就写了一个回声服务器而且在那篇博客的基础上列举了一些大家写最基本的回声服务器会遇到的一些错误情况。因为本篇博客也是写回声服务器所以我会基于之前的那两篇博客来发挥,主要也就是增加一部分测试案例。


server.c


#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<ctype.h>
#define SERVER_PORT 6666
#define MAXLINE 100
int main(void) {
  /*定义  server端套接字文件描述符:sfd
        client套接字文件描述符:cfd
        read函数读取到的字符数:n */
  int sfd, cfd, n;
  /* server端地址定义(包含IP、PORT、协议族)暂未指定:server_addr
     client端地址定义(包含IP、PORT、协议族)不需要再server.c定义,accept函数会自动填充*/
  struct sockaddr_in server_addr, client_addr;
  socklen_t  client_len;//为 accept函数第三个参数做准备
  char buf[MAXLINE];//接收client端发来的字符的缓冲区
  /*bzero:将server端置空,为了给后续的IP、PORT、协议族赋值所用
   后续操作是为了 bind函数绑定IP、PORT和协议族的固定操作。*/
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;//IPV4
  server_addr.sin_port = htons(SERVER_PORT);//转换为网络字节序
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  sfd = socket(AF_INET, SOCK_STREAM, 0);  //调用 socket函数值后会返回一个文件描述符
  bind(sfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); //绑定IP、PORT、协议族
  listen(sfd, 21);
  /* accept函数放在 while 里面和外面的结果是不一样的,
      accept放在while里面代表客户端只能和服务器端通信一次
      accept放在while外面那么客户端就可以一直和服务器进行通信
  */
  while (1) {
    client_len = sizeof(client_addr);
    cfd = accept(sfd, (struct sockaddr*)&client_addr, &client_len);//accept调用和会给server端返回一个和client端连接好的socket。
    n = read(cfd, buf, MAXLINE);
    for (int i = 0; i < n; i++) {
      buf[i] = toupper(buf[i]);
    }
    write(cfd, buf, n);
    close(cfd);
  }
  return 0;
}

client.c

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<ctype.h>
#define SERVER_PORT 6666
#define MAXLINE 100
int main(void) {
  int sfd, n;
  struct sockaddr_in server_addr;
  char buf[MAXLINE];
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(SERVER_PORT);
  inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
  sfd = socket(AF_INET, SOCK_STREAM, 0);
  connect(sfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
  while (1) {
    fgets(buf, sizeof(buf), stdin);
    write(sfd, buf, strlen(buf));
    n = read(sfd, buf, sizeof(buf));
    write(STDOUT_FILENO, buf, n);
  }
  close(sfd);
  return 0;
}

ssh1:

gcc server.cpp -o server

./server

 

ssh2:

gcc client.cpp -o client

./client

hello server.c


20210426092138513.png

20210426092152110.png

我们可以看到当启动 server端到结束时都没有任何东西(其实我们可以增加一些输出比如说显示客户端的ip地址或者端口号,甚至还可以将转换好的字符串输出数来,可以在后续的博客进行实现,本博客为了简便甚至没有加上出错处理函数,就为了突出整个程序的逻辑!!)


client端:当我们输入:hello server.c,,马上就能得到服务器返回给我们转成大写的字符串,可是当我们在输入字符串的时候服务器已经不理我们了,甚至还结束了我们的连接(原因是因为我们把close函数放在while循环里面的)。


测试

close放在while外会发生什么呢?

20210426093221594.png

结果依旧是服务器只反应了我们的第一个字符串,又因为没有close函数关闭我们可以一直输入字符串,但是服务器都不会再进行响应了。

 

增加需求

 服务器和客户端通讯建立后服务器能够一直回响客服端发来的消息

技术实现:


       将accept函数放在while函数外面,再将close函数放在while函数外面即可。

代码对比:

20210426094157339.png

实现效果:(改变代码之后记得要重新编译源cpp文件)

ssh1:

gcc server.cpp -o server

./server

 


ssh2:

./client

server端的结果和上面是一样的

20210426093852221.png

感谢观看。


目录
相关文章
|
11月前
|
存储 弹性计算 网络协议
阿里云服务器ECS实例规格族是什么?不同规格CPU型号、处理器主频及网络性能参数均不同
阿里云ECS实例规格族是指具有不同性能特点和适用场景的实例类型集合。不同规格族如计算型c9i、通用算力型u1、经济型e等,在CPU型号、主频、网络性能、云盘IOPS等方面存在差异。即使CPU和内存配置相同,性能参数和价格也各不相同,适用于不同业务需求。
727 144
|
存储 运维 API
HPE OneView 10.0 - HPE 服务器、存储和网络设备集中管理软件
HPE OneView 10.0 - HPE 服务器、存储和网络设备集中管理软件
256 1
|
12月前
|
JSON 监控 API
在线网络PING接口检测服务器连通状态免费API教程
接口盒子提供免费PING检测API,可测试域名或IP的连通性与响应速度,支持指定地域节点,适用于服务器运维和网络监控。
2008 0
|
12月前
|
机器学习/深度学习 存储 监控
内部文件审计:企业文件服务器审计对网络安全提升有哪些帮助?
企业文件服务器审计是保障信息安全、确保合规的关键措施。DataSecurity Plus 是由卓豪ManageEngine推出的审计工具,提供全面的文件访问监控、实时异常告警、用户行为分析及合规报告生成功能,助力企业防范数据泄露风险,满足GDPR、等保等多项合规要求,为企业的稳健发展保驾护航。
349 0
|
C# 图形学 开发者
Unity开发中使用UnityWebRequest从HTTP服务器下载资源。
总之,UnityWebRequest就是游戏开发者手中的万能钓鱼竿,既可以获取文本数据,也能钓上图片资源,甚至是那声音的涟漪。使用UnityWebRequest的时候,你需要精心准备,比如确定URL、配置请求类型和头信息;发起请求;巧妙处理钓获的数据;还需要机智面对网络波澜,处理各种可能出现的错误。按照这样的过程,数据的钓取将会是一次既轻松愉快也效率高效的编程钓鱼之旅。
749 18
|
11月前
|
存储 监控 Linux
Dell OpenManage Enterprise 4.5 - Dell 服务器、存储和网络设备集中管理软件
Dell OpenManage Enterprise 4.5 - Dell 服务器、存储和网络设备集中管理软件
284 0
|
存储 安全 Linux
Dell OpenManage Enterprise 4.4 - Dell 服务器、存储和网络设备集中管理软件
Dell OpenManage Enterprise 4.4 - Dell 服务器、存储和网络设备集中管理软件
454 4
Dell OpenManage Enterprise 4.4 - Dell 服务器、存储和网络设备集中管理软件
|
存储 消息中间件 弹性计算
阿里云服务器ECS计算型c7和通用算力型u1在适用场景、计算性能、网络与存储性能等方面的对比
阿里云ECS服务器u1和c7实例在适用场景、性能、处理器特性等方面存在显著差异。u1为通用算力型,性价比高,适合中小企业及对性能要求不高的场景;c7为企业级计算型,采用最新Intel处理器,性能稳定且强大,适用于高性能计算需求。u1支持多种CPU内存配比,但性能一致性可能受底层平台影响;c7固定调度模式,确保高性能与稳定性。选择时可根据预算与性能需求决定。
619 23
|
SQL 数据采集 人工智能
“服务器老被黑?那是你没上AI哨兵!”——聊聊基于AI的网络攻击检测那些事儿
“服务器老被黑?那是你没上AI哨兵!”——聊聊基于AI的网络攻击检测那些事儿
535 12