当前位置: 首页 > wzjs >正文

建设一个好的网站网站修改图片怎么做

建设一个好的网站,网站修改图片怎么做,分类信息网发布大全,怎么找到域名做的那个网站知识点1【项目功能介绍】 今天我们写一个 UDP ,多进程与不同进程间通信的综合练习 我这里说一下 这个项目的功能: 1、群发(有设备个数的限制):发送数据,其他所有客户端都要受到数据 2、其他客户端 都 可…

知识点1【项目功能介绍】

今天我们写一个 UDP多进程不同进程间通信的综合练习

我这里说一下 这个项目的功能:

1、群发(有设备个数的限制):发送数据,其他所有客户端都要受到数据

2、其他客户端 可以向本机发送消息

3、私发:私发的格式为 /IP:端口号,数据

知识点2【项目实现思路】

1、首先最基本的UDP的步骤

创建套接字→绑定套接字→操作→关闭套接字

2、创建两个子进程,一个子进程负责收数据,另一个子进程负责发数据

3、由于子进程之间 都需要 所连接的设备的 IP 和 端口号,但是子进程之间的空间又是独立的,因此我们需要用共享内存的方式,而共享内存共享的则是一个地址结构体数组

1、共享结构体数组

    char shm_name[32] = "./shm_file";int fd_shm = open(shm_name,O_CREAT | O_RDWR,0666);if(fd_shm < 0){perror("open");_exit(-1);}int shm_size = sizeof(struct sockaddr_in) * NUM_DEVICE;//2、设置共享内存大小ftruncate(fd_shm,shm_size);//3、内存映射struct sockaddr_in * sockaddr_shm = (struct sockaddr_in *)mmap(NULL,shm_size,PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);if(sockaddr_shm  == MAP_FAILED){perror("mmap");_exit(-1);}bzero(sockaddr_shm,shm_size);

1、首先打开文件(可读可写,创建)

2、由于文件打开,大小为0,我们需要进行扩容

ftruncate();

3、内存映射mmap

NULL(系统自动寻找内存空间),空间大小,文件权限,共享,要映射的文件,偏移量

4、清空内存

bzero();

2、UDP常规流程

创建套接字 和 绑定

		//套接字创建int fd_sock = socket(AF_INET,SOCK_DGRAM,0);if(fd_sock < 0){perror("socket");_exit(-1);}//绑定struct sockaddr_in addr_src;addr_src.sin_family = AF_INET;addr_src.sin_port = htons(8000);addr_src.sin_addr.s_addr = htonl(INADDR_ANY); int ret_bind = bind(fd_sock,(struct sockaddr *)&addr_src,sizeof(addr_src));if(ret_bind < 0){perror("bind");_exit(-1);}

不多作介绍

3、创建子进程的模式

以创建两个为例

    //创建子进程size_t i = 0;for (; i < 2; i++){int pid = fork();if(pid < 0){perror("fork");_exit(-1);}if(pid == 0){break;}}if(i == 0)//子进程1{}else if(i == 1)//子进程2{}

不多作介绍

4、收数据

    if(i == 0)//进程1,负责收数据{while(1){char buf[500] = "";int len = sizeof(struct sockaddr_in);struct sockaddr_in buf_recv;int ret_recv = recvfrom(fd_sock,buf,sizeof(buf),0,(struct sockaddr *)&buf_recv,&len);if(ret_recv < 0){perror("recvfrom");_exit(-1);}//查看该IP和端口是否存在int exists = 0;for (size_t j = 0; j < NUM_DEVICE; j++){if(buf_recv.sin_addr.s_addr == sockaddr_shm[j].sin_addr.s_addr && buf_recv.sin_port == sockaddr_shm[j].sin_port){exists = 1;break;}}if(exists != 1)//不存在,存入第一个空的地址结构体{size_t k = 0;for (; k < NUM_DEVICE; k++){if(ntohs(sockaddr_shm[k].sin_port) == 0){memcpy(&sockaddr_shm[k],&buf_recv,sizeof(buf_recv));//代码书写过程中,这里出现错误 break;}}if(k == NUM_DEVICE){printf("\\r群聊已满,无法加入\\n");continue;}}//遍历收到的信息char buf_IP[16] = "";inet_ntop(AF_INET,&buf_recv.sin_addr.s_addr,buf_IP,sizeof(buf_IP));int port = ntohs(buf_recv.sin_port);printf("\\r收到IP:%s,端口号:%d的信息为:%s\\n",buf_IP,port,buf);printf("\\r请输入数据(提示/起始可指定IP发送):");fflush(stdout);}_exit(-1);}

思路讲解

1、首先接收数据

2、判断数据来源客户端,是否存在,如果不存在,则存在 结构体数组的 最小有效的下标 中,当数组存满后,需要提醒一下,但是不会退出,已经连接的设备仍然可以发送/接收数据,因此需要用continue而不是break

这里我要说我写的过程中的一个错误,希望大家以我为诫,别犯类似错误

我在下面代码中,数组下标忘记写了&sockaddr_shm[k]→sockaddr_shm,导致我永远只能给一台设备发送数据

for (; k < NUM_DEVICE; k++)
{if(ntohs(sockaddr_shm[k].sin_port) == 0){memcpy(&sockaddr_shm[k],&buf_recv,sizeof(buf_recv));//代码书写过程中,这里出现错误 break;}
}

3、遍历收到的数据

5、发数据

else if(i == 1){   while(1){printf("\\r请输入数据(提示/起始可指定IP发送):");fflush(stdout);char buf[256] = "";fgets(buf,sizeof(buf),stdin);buf[strlen(buf) - 1] = 0;if(buf[0] == '/'){char buf_ip[16] = "";int int_port = 0;char data[256] = "";sscanf(buf,"/%[^:]:%4d,%s",buf_ip,&int_port,data);int int_ip = 0;//转为网络字节序inet_pton(AF_INET,buf_ip,&int_ip);int_port = htons(int_port);//定义一个标志位,判断输入的端口是不是存在int flag = 0;size_t k = 0;for (; k < NUM_DEVICE; k++){if(sockaddr_shm[k].sin_addr.s_addr == int_ip && sockaddr_shm[k].sin_port == int_port){flag = 1;break;}}if(flag == 1){//私发sendto(fd_sock,data,sizeof(data),0,(struct sockaddr *)&sockaddr_shm[k],sizeof(struct sockaddr_in));}else{//不存在该端口,打印提示内容,输出现有的所有IP和端口printf("指令错误,请按照下面的model输入\\n");printf("mode:/192.168.6.3:9000,data\\n");if(sockaddr_shm[0].sin_addr.s_addr != 0);{printf("以下是已经连接的端口\\n");for (size_t i = 0; i < NUM_DEVICE; i++){if(sockaddr_shm[i].sin_port != 0){inet_ntop(AF_INET,&sockaddr_shm[i].sin_addr.s_addr,buf_ip,sizeof(buf_ip));int_ip = ntohs(sockaddr_shm->sin_port);printf("%s:%d\\n",buf_ip,int_ip);}}}}}else//群发{for (size_t j = 0; j < NUM_DEVICE ;j++){if(sockaddr_shm[j].sin_port != 0){sendto(fd_sock,buf,sizeof(buf),0,(struct sockaddr *)&sockaddr_shm[j],sizeof(struct sockaddr_in));}}}}}

思路讲解

1、观察格式,我们发现私发格式 第一个字母必须要求是/开头,我们用这个作为进行判断

2、首先需要判断输入的端口 和 IP地址是否合法

3、如果合法,进行发送,不合法则需要 遍历提示内容,如果已经有设备的连接,需要遍历出可以通信的IP

注意

这一步比较复杂的是数据类型(网络字节序与主机字节序的转换,与点分法十进制串与 网络整形IP 的转换)

6、父进程负责回收空间

    else{while(1){int ret_wait = waitpid(-1,NULL,WNOHANG);if(ret_wait < 0){break;}}close(fd_shm);close(fd_sock);munmap(shm_name,shm_size);remove(shm_name);}

需要回收的空间介绍

1、共享内存时 打开的共享内存文件描述符

2、套接字

3、映射关系

4、映射文件删除

知识点2【整体代码演示】

//项目介绍 实现多人聊天室
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include <strings.h>
#include <string.h>
#include <stdlib.h>#define NUM_DEVICE 10int main(int argc, char const *argv[])
{//父进程负责管理子进程的内存,子进程1负责收,子进程2 负责发//收的流程,创建sock,绑定端口,收,关闭端口//发的流程,创建sock,绑定端口,发,变比端口//由于需要子进程之间需要共享 结构体数组数据,这里需要利用到共享内存//1、创建共享内存,并计算大小char shm_name[32] = "./shm_file";int fd_shm = open(shm_name,O_CREAT | O_RDWR,0666);if(fd_shm < 0){perror("open");_exit(-1);}int shm_size = sizeof(struct sockaddr_in) * NUM_DEVICE;//2、设置共享内存大小ftruncate(fd_shm,shm_size);//3、内存映射struct sockaddr_in * sockaddr_shm = (struct sockaddr_in *)mmap(NULL,shm_size,PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);if(sockaddr_shm  == MAP_FAILED){perror("mmap");_exit(-1);}bzero(sockaddr_shm,shm_size);//套接字创建int fd_sock = socket(AF_INET,SOCK_DGRAM,0);if(fd_sock < 0){perror("socket");_exit(-1);}//绑定struct sockaddr_in addr_src;addr_src.sin_family = AF_INET;addr_src.sin_port = htons(8000);addr_src.sin_addr.s_addr = htonl(INADDR_ANY); int ret_bind = bind(fd_sock,(struct sockaddr *)&addr_src,sizeof(addr_src));if(ret_bind < 0){perror("bind");_exit(-1);}//创建子进程size_t i = 0;for (; i < 2; i++){int pid = fork();if(pid < 0){perror("fork");_exit(-1);}if(pid == 0){break;}}//子进程1 负责收if(i == 0){while(1){char buf[500] = "";int len = sizeof(struct sockaddr_in);struct sockaddr_in buf_recv;int ret_recv = recvfrom(fd_sock,buf,sizeof(buf),0,(struct sockaddr *)&buf_recv,&len);if(ret_recv < 0){perror("recvfrom");_exit(-1);}//查看该IP和端口是否存在int exists = 0;for (size_t j = 0; j < NUM_DEVICE; j++){if(buf_recv.sin_addr.s_addr == sockaddr_shm[j].sin_addr.s_addr && buf_recv.sin_port == sockaddr_shm[j].sin_port){exists = 1;break;}}if(exists != 1)//不存在,存入第一个空的地址结构体{size_t k = 0;for (; k < NUM_DEVICE; k++){if(ntohs(sockaddr_shm[k].sin_port) == 0){memcpy(&sockaddr_shm[k],&buf_recv,sizeof(buf_recv));//代码书写过程中,这里出现错误 break;}}if(k == NUM_DEVICE){printf("\\r群聊已满,无法加入\\n");continue;}}//遍历收到的信息char buf_IP[16] = "";inet_ntop(AF_INET,&buf_recv.sin_addr.s_addr,buf_IP,sizeof(buf_IP));int port = ntohs(buf_recv.sin_port);printf("\\r收到IP:%s,端口号:%d的信息为:%s\\n",buf_IP,port,buf);printf("\\r请输入数据(提示/起始可指定IP发送):");fflush(stdout);}_exit(-1);}//子进程2 负责发,这里设置,如果发送收到bye,Bye退出//实现发送消息,实际上是给多人发送,使用 结构体数组,存储多人的信息else if(i == 1){   while(1){printf("\\r请输入数据(提示/起始可指定IP发送):");fflush(stdout);char buf[256] = "";fgets(buf,sizeof(buf),stdin);buf[strlen(buf) - 1] = 0;if(buf[0] == '/'){char buf_ip[16] = "";int int_port = 0;char data[256] = "";sscanf(buf,"/%[^:]:%4d,%s",buf_ip,&int_port,data);int int_ip = 0;//转为网络字节序inet_pton(AF_INET,buf_ip,&int_ip);int_port = htons(int_port);//定义一个标志位,判断输入的端口是不是存在int flag = 0;size_t k = 0;for (; k < NUM_DEVICE; k++){if(sockaddr_shm[k].sin_addr.s_addr == int_ip && sockaddr_shm[k].sin_port == int_port){flag = 1;break;}}if(flag == 1){//私发sendto(fd_sock,data,sizeof(data),0,(struct sockaddr *)&sockaddr_shm[k],sizeof(struct sockaddr_in));}else{//不存在该端口,打印提示内容,输出现有的所有IP和端口printf("指令错误,请按照下面的model输入\\n");printf("mode:/192.168.6.3:9000,data\\n");if(sockaddr_shm[0].sin_addr.s_addr != 0);{printf("以下是已经连接的端口\\n");for (size_t i = 0; i < NUM_DEVICE; i++){if(sockaddr_shm[i].sin_port != 0){inet_ntop(AF_INET,&sockaddr_shm[i].sin_addr.s_addr,buf_ip,sizeof(buf_ip));int_ip = ntohs(sockaddr_shm->sin_port);printf("%s:%d\\n",buf_ip,int_ip);}}}}}else{for (size_t j = 0; j < NUM_DEVICE ;j++){if(sockaddr_shm[j].sin_port != 0){sendto(fd_sock,buf,sizeof(buf),0,(struct sockaddr *)&sockaddr_shm[j],sizeof(struct sockaddr_in));}}}}}//父进程回收子进程else{while(1){int ret_wait = waitpid(-1,NULL,WNOHANG);if(ret_wait < 0){break;}}close(fd_shm);close(fd_sock);munmap(shm_name,shm_size);remove(shm_name);}return 0;
}

代码运行结果

结束

代码重在练习!

代码重在练习!

代码重在练习!

今天的分享就到此结束了,希望对你有所帮助,如果你喜欢我的分享,请点赞收藏夹关注,谢谢大家!!!


文章转载自:

http://2ygIHuAw.smcfk.cn
http://mqtZcEaA.smcfk.cn
http://rtIGviAS.smcfk.cn
http://ACwbp9sH.smcfk.cn
http://Llwk0G1Q.smcfk.cn
http://HIAeueV3.smcfk.cn
http://DzZ2xrkW.smcfk.cn
http://QI1svO67.smcfk.cn
http://FhszCUFy.smcfk.cn
http://3a984de6.smcfk.cn
http://Vncqg1aS.smcfk.cn
http://BuVHIJdw.smcfk.cn
http://520on4Gm.smcfk.cn
http://3ODsYgDo.smcfk.cn
http://Dp3gZFqY.smcfk.cn
http://Hpx9wfzA.smcfk.cn
http://FS1sdZT2.smcfk.cn
http://RoRo0fGr.smcfk.cn
http://g5FXDwQc.smcfk.cn
http://XeUxlTAE.smcfk.cn
http://0cttsKyN.smcfk.cn
http://W3HMPulx.smcfk.cn
http://FU7E1pD1.smcfk.cn
http://5UmHeBYr.smcfk.cn
http://Bxm4dn83.smcfk.cn
http://S5QDaoya.smcfk.cn
http://Jf1iCroi.smcfk.cn
http://4nRk7oVO.smcfk.cn
http://pjrcMNZ3.smcfk.cn
http://X1yfUBO0.smcfk.cn
http://www.dtcms.com/wzjs/702943.html

相关文章:

  • 南京华典建设有限公司网站郑州做企业网站
  • 3800给做网站河南省二级建造师报名入口官网
  • 做网站没有做退钱酷炫网站模板
  • 攀枝花网站建设wordpress 调用
  • 站长工具查询网站渭南免费做网站
  • 押注网站建设php不用框架怎么做网站
  • 大连新图闻网站设计php企业网站多少钱
  • 网站营销单页面留言wordpress mu 模板
  • 建设部规范网站网站 设计 深圳
  • 西安房地产网站建设产品设计考研学校
  • 网站建设开发技术天津北京律师网站建设平台
  • 餐饮logo设计泉州关键词优化推广
  • 网站开发的prd 怎么写吸引人的微信软文范例
  • 企业网站建设一条龙多少钱wordpress安全设置
  • 网站 设计 趋势wordpress问答插件中文免费版
  • 北京网站定制制作夸克作文网站
  • 大龄网站开发人员dz多语言企业网站
  • 洛阳建站莱芜金点子电子版报纸
  • 海南省住房和城乡建设官方网站茶叶电子商务网站建设的结论
  • 网站注册局广东集团网站建设
  • 做室内意向图的网站租服务器网站
  • 网站建设的相关论文软件下载网站知乎
  • 上海网站公门户网站开发要求
  • 网站开发心得沈阳招标中心招标公告
  • 建筑公司网站源码群晖可以做网站服务器
  • 网站空间服务多少钱深圳南山建设局官方网站
  • 北京网站建设推荐q479185700上快保定网站优化哪家好
  • 吉林建设工程信息网站网站服务器信息查询
  • 网站开发需要会啥交通建设网站
  • 金融类网站建设wordpress怎么改登陆不了