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

感谢观看。


目录
相关文章
|
18天前
|
机器学习/深度学习 人工智能 运维
企业内训|LLM大模型在服务器和IT网络运维中的应用-某日企IT运维部门
本课程是为某在华日资企业集团的IT运维部门专门定制开发的企业培训课程,本课程旨在深入探讨大型语言模型(LLM)在服务器及IT网络运维中的应用,结合当前技术趋势与行业需求,帮助学员掌握LLM如何为运维工作赋能。通过系统的理论讲解与实践操作,学员将了解LLM的基本知识、模型架构及其在实际运维场景中的应用,如日志分析、故障诊断、网络安全与性能优化等。
44 2
|
23天前
|
存储 安全 数据可视化
提升网络安全防御有效性,服务器DDoS防御软件解读
提升网络安全防御有效性,服务器DDoS防御软件解读
38 1
提升网络安全防御有效性,服务器DDoS防御软件解读
|
12天前
|
关系型数据库 API 数据库
后端开发的艺术:从零到一构建高效服务器
在数字化时代,后端开发是支撑现代互联网应用的基石。本文旨在探讨后端开发的核心概念、关键技术以及如何构建一个高效的服务器。我们将从基础的编程语言选择开始,逐步深入到数据库设计、API开发和性能优化等关键领域。通过实际案例分析,我们将揭示后端开发的复杂性和挑战性,同时提供实用的解决方案和最佳实践。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和启发。
|
10天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
179 1
|
25天前
|
网络安全 Docker 容器
VScode远程服务器之远程 远程容器 进行开发(五)
VScode远程服务器之远程 远程容器 进行开发(五)
21 1
|
1月前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
360 1
|
1月前
|
网络协议 Java API
【网络】TCP回显服务器和客户端的构造,以及相关bug解决方法
【网络】TCP回显服务器和客户端的构造,以及相关bug解决方法
59 2
|
1月前
|
存储 网络协议 Java
【网络】UDP回显服务器和客户端的构造,以及连接流程
【网络】UDP回显服务器和客户端的构造,以及连接流程
49 2
|
16天前
|
NoSQL PHP Redis
布谷语音app源码服务器环境配置及技术开发语言
布谷语音app源码服务器环境配置及技术语言研发。。
|
24天前
|
安全 区块链 数据库
下一篇
无影云桌面