错误的尝试:回射程序改进2(代码片段)

lnlin lnlin     2022-12-28     666

关键词:

在回射程序的基础上,设计一个类似于群聊的应用

与改进1相比增加的设计:

1.将每个客户端发出的消息增加一个字符串,用于表示发送者的身份

2.服务端将收到的每个客户端消息转发给其他已连接的客户端套接字

改进1:https://www.cnblogs.com/lnlin/p/9568279.html

改进的思考过程:

1.消息头的增加:

增加一个客户端mian函数参数,用于表示用户名。

将每个客户端用户名添加到客户端发送的消息头部来表名某个消息发送者的身份,添加方式:

a.在客户端在标准输入输入消息后,客户端自动将此客户端用户用户名字符串添加到消息头部,再将

添加了用户名的消息发送给服务端

b.在客户端与服务端建立连接后,将客户端用户名发送给服务端,服务端保存此用户名,并在转发客

户端消息时,将相应用户名添加到相应消息数据中

下面的实现选用 a 方法,原因是我考虑到这么做虽然增加了客户端发送给服务端的消息长度,但减少

了客户端所需要的操作。

客户端main函数:

  1 #include "net.h"
  2 
  3 int main(int argc, char **argv)
  4 
  5     int sockfd;
  6 
  7     if (argc != 3)
  8     
  9         printf("Error arg!
");
 10         exit(1);
 11     
 12 
 13     printf("%s
", argv[2]);
 14 
 15     sockfd = tcp_connect(argv[1], SERV_PORT);
 16     printf("Success init, the connected socket is %d
", sockfd);
 17     cli_io(sockfd, argv[2]);
 18 
 19     return 0;
 20 

将一个字符串添加到另一个字符串头部:

 35 // 将一个字符串放到另一个字符串的头部,构造将用户名加到客户发送的消息中
 36 // 不提供对字符串空间大小的检查
 37 char *addStrHead(char *head, char *row)
 38 
 39     int headLen, rowLen, i;
 40     headLen = strlen(head);
 41     rowLen = strlen(row);
 42 
 43     for (i = headLen + rowLen; i >= 0; i--)
 44     
 45         if (i > headLen)
 46         
 47             row[i] = row[i - headLen - 1];
 48         
 49         else if (i == headLen)
 50         
 51             row[i] = :;
 52         
 53         else
 54         
 55             row[i] = head[i];
 56         
 57     
 58 
 59     row[headLen + rowLen + 1] = ;
 60 
 61     return row;
 62 

与改进1相比变化的cli_io函数:

 64 // 回射程序客户端对套接字的读写
 65 void cli_io(int sockfd, char *mark)
 66 
 67     int n;
 68     char sendline[MAXLINE], recvline[MAXLINE];
 69 
 70     while (fgets(sendline, MAXLINE, stdin) != NULL)
 71     
 72         // 将用户名添加到消息头部
 73         addStrHead(mark, sendline);
 74         
 75         if (write(sockfd, sendline, strlen(sendline)) < 0)
 76            
 77             printf("Error write!
");
 78             exit(1);
 79         
 80         
 81         if ( (n = read(sockfd, recvline, MAXLINE)) > 0 )
 82            
 83             recvline[n] = ;
 84             fputs(recvline, stdout);
 85         
 86     
 87     
 88     return;
 89 

服务端改进:

将从客户端收到的消息转发自其他已连接套接字

错误的尝试:在使用fork创建子进程的方式来处理每个自连接的基础上,在服务端添加一个结构用于保

存所有连接过的套接字与相应套接字的存活状态,每个子进程在收到此消息后通过此套接字列表转发消

息。

错误原因思考:如果父进程先创建子进程,后父进程生成socket,这些socket和子进程无关

服务端代码:

  1 #include "net.h"
  2 
  3 
  4 int main(int argc, char **argv)
  5 
  6     int listenfd, connfd, n;
  7     struct sockaddr_in cliaddr;
  8     pid_t childpid;
  9     socklen_t clilen;
 10 
 11     // 为所有与服务器建立连接的套接字创建一个存储数组
 12     struct sockConn socklist[MAXSOCKET];
 13     int cntSockfd = 0;
 14     listenfd = tcp_listen(SERV_PORT);
 15     for ( ; ; )
 16     
 17         clilen = sizeof(cliaddr);
 18 
 19         if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0 )
 20         
 21             printf("Error accept!
");
 22             exit(0);
 23         
 24 
 25         printf("accept: %d
", connfd);
 26 
 27         addSockfd(connfd, socklist, &cntSockfd);
 28 
 29         if ( (childpid = fork()) == 0 )
 30         
 31             if (close(listenfd) < 0)
 32             
 33                 printf("Error close!
");
 34                 exit(1);
 35             
 36 
 37             serv_io(connfd, socklist, &cntSockfd);
 38             exit(0);
 39         
 40     
 41 

所用函数:

 35 // 将从某一客户端接收的数据群发到所有已连接的客户(套接字)
 36 void send2All(char *message, int itself, struct sockConn *socklist, int *cntSockfd)
 37 
 38     int i;
 39 
 40     for (i = 0; i < *cntSockfd; i++)
 41     
 42         if (socklist[i].used && socklist[i].sockfd != itself)
 43         
 44             if (write(socklist[i].sockfd, message, strlen(message)) < 0)
 45             
 46                 printf("Error write!
");
 47                 exit(1);
 48             
 49         
 50     
 51 
 52     return;
 53 
 54 
 55 // 服务端io
 56 void serv_io(int connfd, struct sockConn *socklist, int *cntSockfd)
 57 
 58     char buff[MAXLINE];
 59     int n;
 60 
 61     while ( (n = read(connfd, buff, MAXLINE)) > 0 )
 62     
 63         buff[n] = ;
 64         fputs(buff, stdout);
 65 
 66         if (write(connfd, buff, strlen(buff)) < 0)
 67         
 68             printf("Error write!
");
 69             exit(1);
 70         
 71 
 72         //send2All(buff, connfd, socklist, cntSockfd);
 73     
 74 
 75     return;
 76 
 77 
 78 // 在accept后将已连接套接字加入socklist,并将已连接过的套接字数加一
 79 void addSockfd(int sockfd, struct sockConn *socklist, int *cntSockfd)
 80 
 81     socklist[*cntSockfd].sockfd = sockfd;
 82     socklist[*cntSockfd].used = 1;
 83     *cntSockfd++;
 84 
 85     return;
 86 
 87 

 

springboot系列之动态定时程序改进版(代码片段)

业务场景基于上篇博客,做了一版动态定时程序,然后发现这个定时程序需要在下次执行的时候会加载新的时间,所以如果改了定时程序不能马上触发,所以想到一种方法,在保存定时程序的时候将cron表达式... 查看详情

手把手写c++服务器(29):手撕echo回射服务器代码(代码片段)

...关服务器。今天我们主要利用splice来实现一个简单的echo回射服务 查看详情

flutter学习-flutter开发初体验(代码片段)

...习-flutter开发初体验1.flutter项目的创建1.1创建方式1.2默认程序分析2.编写flutter代码2.1helloworld的实现2.2代码分析2.2.1runApp和Widget2.2.2Material设计风格2.3代码改进2.3.1改进界面样式2.3.2改进界面结构2.3.3进阶案例实现2.4代码重构2.4.1创建... 查看详情

java排序(七大排序合集)(代码片段)

...排序1.1、排序过程图1.2、排序思想1.3、排序代码1.4、代码改进2、选择排序2.1、排序过程图2.2、排序思想2.3、排序代码2.4、代码改进——双向选择排序2.4.1、改进排序思想2.4.2、改进排序代码3、插入排序3.1、排序过程图3.2、排序思... 查看详情

springboot系列之动态定时程序改进版(代码片段)

业务场景基于上篇博客,做了一版动态定时程序,然后发现这个定时程序需要在下次执行的时候会加载新的时间,所以如果改了定时程序不能马上触发,所以想到一种方法,在保存定时程序的时候将cron表达式... 查看详情

springboot系列之动态定时程序改进版(代码片段)

业务场景基于上篇博客,做了一版动态定时程序,然后发现这个定时程序需要在下次执行的时候会加载新的时间,所以如果改了定时程序不能马上触发,所以想到一种方法,在保存定时程序的时候将cron表达式... 查看详情

《unix网络编程卷1:套接字联网api》学习笔记——tcp客户/服务器程序示例(代码片段)

UNIX网络编程——TCP客户/服务器程序示例概述TCP回射服务器程序:main函数TCP回射服务器程序:str_echo函数TCP回射客户程序:main函数TCP回射客户程序:str_cli函数正常启动正常终止服务器主机崩溃服务器主机崩溃后重... 查看详情

结对编程作业(代码片段)

...ncheng二.需求分析针对现有代码的改进分析:1.修改了一些程序功能上的bug。在重复点击确认键是,计算的正确率有误。2.对界面进行了改进新开发功能的分析:1.增加了关于整数的乘方运算符三.程序设计关于整个程序的流程设计... 查看详情

网络四则运算结对编程(代码片段)

...并加了括号改进后界面:改进前类图:改进后类图:2、程序设计3、代码展示关键代码展示:··· 查看详情

如何用几行代码改进这个程序? [关闭]

...losed]【发布时间】:2021-02-1811:35:17【问题描述】:我正在尝试创建一个不和谐的机器人来检查消息是否包含存储在数组中的字符串。我尝试使用for循环但它不起作用,因为它永远持续,我想减少代码行数,有什么办法吗?switchcas... 查看详情

python异常(代码片段)

程序在运行时,如果 Python解释器 遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常程序停止执行并且提示错误信息 这个动作,我们通常称之为:抛出(raise)异常 简单的捕获异常... 查看详情

java排序(七大排序合集)(代码片段)

...排序1.1、排序过程图1.2、排序思想1.3、排序代码1.4、代码改进2、选择排序2.1、排序过程图2.2、排序思想2.3、排序代码2.4、代码改进——双向选择排序2.4.1、改进排序思想2.4.2、改进排序代码3、插入排序3.1、排序过程图3.2、排序思... 查看详情

mingw的windows10make工具返回错误2(e=2)(代码片段)

...使make实用程序执行的任务不是来自MinGW的命令时仍然遇到错误2。test:test.cppg++-otesttest.cppclean:rm./*.exe编译工作正常,但当我尝试运行干净,我得到一个错误。PSD:ProgramsC++Test>makecleanrm./*.exeprocess_begin:CreateProcess(NULL,rm./*.exe,...)failed.... 查看详情

从 g++/gcc 3.2.3 到 4.2.4 的性能改进

...进非常显着。我已尝试搜索gccbuzilladatabase以查找有关哪些错误可能有如此显着改进的提示,但我没有找到任何 查看详情

异常处理(代码片段)

...、基本概念1、什么是异常  所谓程序中的异常,就是错误发生的信号,也就是说当程序出错并且程序没有处理这个错误,则会抛出一个异常,并且程序会随着这个异常终止。2、程序中错误的分类:(1)语法错误:  语法错... 查看详情

unp学习第五章

...要写一个完整的TCP客户-服务器程序例子,有下面功能的回射服务器1.客户从标准输入读一行文本,写到服务器上;2.服务器从网络输入读此行,并回射给客户;3.客户读此回射行并写到标准输出。此例子需要观察:正常运行时什... 查看详情

改进计算器(代码片段)

只改了主程序calc.cpp1#include<iostream>2#include"Comp.h"3#include"Isop.h"4#include<stack>5#include<string>6#include<math.h>7usingnamespacestd;8/**91.接收用户输入//没有判断是否有非法字符102.处理113.输出12 查看详情

时隔半年再写购物车程序并改进(代码片段)

时隔了半年时间,重新把购物车程序拿出来再写一遍,感觉对于循环语句比之前熟悉多了,脑子里面开始有程序流程图,之前懵懵懂懂地跟着老师来写,现在基本可以自己写,自己判断问题出在哪里了。这段程序没用pycharm来写... 查看详情