php网站开发怎么样专业做网站哪个公司好
- 作者: 多梦笔记
- 时间: 2026年02月17日 15:15
当前位置: 首页 > news >正文
php网站开发怎么样,专业做网站哪个公司好,江苏镇江扬中贴吧,门户网站 制作多少钱目录 前提知识
- 理解源ip#xff0c;目的ip和Macip
- 端口号
- 初识TCP#xff0c;UDP协议
- 网络字节序
- socket 编程
sockaddr类型
一#xff0c;基于udp协议编程
- socket——创建套接字
- bind——将套接字强绑定
- recvfrom——接受数据
- s…目录 前提知识
- 理解源ip目的ip和Macip
- 端口号
- 初识TCPUDP协议 4. 网络字节序
- socket 编程 sockaddr类型 一基于udp协议编程
- socket——创建套接字
- bind——将套接字强绑定
- recvfrom——接受数据
- sendto——发出信息 遇到的问题
- 云服务器中以及无法分配IP问题
- IP127.0.0.1更深层次的认识
- 关于服务端bind的优化 源码 二基于tcp协议编程
- listen——服务端监听
- accept——服务端接收
- connect——客户端请求
- send recev 三基于TCP协议实现的线程池的服务端对客户端进行相互通信小项目 结构图一览 源码
- 单进程处理 2. 子进程处理 2.1. 孙子进程处理
- 多线程处理
- 线程池处理 下期TCP协议原理 结语 嗨收到一张超美的风景图愿你每天都能顺心 前提知识
- 理解源ip目的ip和Macip 数据在以太网上传输经过多个路由器Mac地址多次封装解包是变化的(可以理解为数据的下一个主机地址)而源ip尤其是目的ip一般是不会改变。 2. 端口号 端口号 (port) 是传输层协议的内容 端口号是一个2字节16位的整数uint16_t;端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;一个端口号只能被一个进程占用标识一台主机进程的唯一性 理解假设客户发送操作在终端应用为A在另一台机器的服务器应用为BA向B发送操作请求本质上是不同机器之间进程间通信请求数据经过封装传递解包后B所在的操作系统将数据根据端口号交给那个进程处理。 同理我们就能理解源端口号就是发出数据的进程目的端口号处理数据的进程 。 因此IP地址 端口号能够标识网络上的唯一台主机的唯一一个进程; 注意 1.一个进程可以有多个端口号绑定但一个端口不能被多个进程绑定。 2. pid是系统管理进程的唯一标识符与端口号没有联系。 同时{IP地址 端口号}的模式被叫做套接字网络通信用套接字的方法实现网络编程也可以被叫做套接字编程。 3. 初识TCPUDP协议 首先我们来找找他们传输层上的这两协议 这里我们只了解两协议的特点具体我们后面再结合场景理解 各自特点 TCP(Transmission Control Protocol 传输控制协议) 传输层协议有连接是否需要手动连接——神似打电话可靠传输对数据包检测丢包重传等等面向字节流后面再提 UDP(User Datagram Protocol 用户数据报协议) 传输层协议无连接不用连接就可以发送——神似发邮件不可靠传输不关心是否丢包面向数据报后面再说 4. 网络字节序 说到字节序我们是否想到C语言中学过的大小端字节序那个是数据在内存中的存储方式。大小端可参见整型浮点型深刻理解【C语言】【整型 || 原反补码 || 浮点型 || 大小端字节序】_小端浮点数-CSDN博客 现在我们讨论的则是数据在向网络发送时是从低字节向高地址发送小端还是从高字节向高地址发送大端。 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分 . 那么如何 定义网络数据流的地址 呢 ? 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出; 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存; 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址. TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节. 不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据; 如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可 为使网络程序具有可移植性 , 使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换 注h是host 主机n是networkl是32位下long4byte;s是16位的short(2byte) 意思是以htonl为例主机字节转网络字节序返回数据。 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回; 如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回。 5. socket 编程 首先我们先简单了解常用的三中套接字 域用socket (基于网络socket下的本地模式类似于命名管道可参见进程通信知识基础【Linux】——下篇【命名管道共享内存信号量初识】-CSDN博客原始socket 一般用于一些工具制作——跳过传输层协议直接用于网络层甚至数据链路层网络socket 很明显上面是适用于三种不同的场景理论上需要三套不同的接口但linux选择只设计一套公用的接口如下 // 创建 socket 文件描述符 (TCP/UDP, 客户端 服务器) int socket(int domain, int type, int protocol); // 绑定端口号 (TCP/UDP, 服务器) int bind(int socket, const struct sockaddr address, socklen_t address_len); // 开始监听socket (TCP, 服务器) int listen(int socket, int backlog); // 接收请求 (TCP, 服务器) int accept(int socket, struct sockaddr address, socklen_t* address_len); // 建立连接 (TCP, 客户端) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); socket API 是一层抽象的网络编程接口 , 适用于各种底层网络协议 , 如 IPv4 、 IPv6, 以及后面要讲的 UNIX Domain Socket. 然而 , 各种网络协议的地址格式并不相同 难道不会有冲突有的但解决了这里我们来看这个参数类型—— sockaddr sockaddr类型 一基于udp协议编程
- socket——创建套接字 socket本质是操作系统对 传输层的接口进行的封装。sys证明来自系统的接口 返回值文件描述符作为返回值 domain: 设置套接字类型网络通信还是本地通信 type: 以 字节流方式发送还是以 数据报形式 protocol: 一般根据前两参数就决定好了设置为0即可。 2. bind——将套接字强绑定 1. bind // 绑定端口号 (TCP/UDP, 服务器) int bind(int socket, const struct sockaddr address, socklen_t address_len); 需要区别C11中std::bind后者是C11的包装器用于函数参数管理。这里的是三种socket通信绑定套接字的通用接口下面是实例 sockaddr_in结构体头文件netinet/in.h // 2.让操作系统将该进程与我们的套接字进行强绑定以便内核中我们信息的获取struct sockaddr_in local;// 全0填充,可以用memsetbzerobzero(local, sizeof bzero);local.sin_family AF_INET; // 设置通信类型// 服务器的ID和端口未来是要将数据发送到网络中数据就需要修改为大端。local.sin_port htons(_port); // 对IP地址补充// 常见的是192.234.222.111——点分十进制字符串风格的IP地址目的用户方便观察// 分成四个领域每个领域都是[0~255],也就是2^8,1字节所以IP,4字节可以完全表示// 如果网络以上面字符串形式传输就是15字节所以需要15字节 - 4字节网络local.sin_addr.s_addr inet_addr(_id.cstr()); //4字节的ID也需要修改if (bind(socket, (sockaddr)local, sizeof local) 0){Logmessage(FATIL, %d:%s\n, errno, strerror(errno));} 如果绑定成功接下来主机就从可以从该套接字中接收数据。 常见的网络转换数据接口具体用法问AI man inet_addr 3. recvfrom——接受数据 参数解析 sockfd: 创建完的套接字返回文件标识符——还是遵从一切为文件buf, len 信息缓冲区flags : 默认为0为阻塞方式接受信息src_addr, addrlen 一个输出型参数收集发送者套接字IP 端口。return : 返回发送者发送字节数。sockaddr, socklen_t 两类型是输出式参数用于记录发送方套接字 4. sendto——发出信息 需要注意的是socklen_t类型需要 使用例子请看下面 功能一个客户端一个服务器在同一台机器上通过IP127.0.0.1来实现互相数据发送。 //服务器启动int start(){char buf[1024];while (1){//1.接受信息struct sockaddr_in peer;bzero(peer, sizeof peer);socklen_t len sizeof peer;ssize_t slen recvfrom(socket, buf, (sizeof buf) - 1, 0, (struct sockaddr)peer, len);if (s_len 0){buf[s_len] 0; // 协议分析这里我们先不说//解析发送目标uint16_t send_port ntohs(peer.sin_port);std::string send_id inet_ntoa(peer.sin_addr);printf(发送方 id:[%s] port:[%d]:%s\n,send_id.c_str(), sendport, buf);}//2.分析信息 //3.发出信息,我们选择发送回sendto(socket, buf, sizeof buf, 0, (struct sockaddr)peer, len);} } 详细代码链接我将放到文章末尾 遇到的问题 1. 云服务器中以及无法分配IP问题 答我们使用云服务器进行代码学习时自己无法分配除127.0.0.1的IP即使是自己的云服务器IP因为是供应商提供的虚拟IP所以云服务器就不允许分配其他IP。 2. IP127.0.0.1更深层次的认识 答为什么可以使用127.0.0.1 IP因为这是一个本地环回的IP在这个IP下数据经过本地协议栈后不会进入网络而是直接从栈底回到操作系统同时这也是适合本地网络服务测试如果接入网络通信没有接通则大概率是网络的原因。 3. 关于服务端bind的优化 答首先我们完善一下从上面代码对bind的认识 修改方法在添加IP地址时将IP修改为任意IP即可。 宏 INADDR_ANY 本质上就是0 关于在Windows下使用客户端 上面创建的客户端都是linux下的客户端如果我们想在Windows下使用 -phread这个第三方库就用不了而客户端就要更改源码库使用window的网络套接字接口但好在几乎类似最后在VS本地运行即可。 自己实现的类一定要进行备注使用方法返回值类型以免代码复用时出现返回值类型问题别问我为啥要单独写一行因为在转类型时转错了一直段错误人都傻了结果后面发现原来是自己实现类的用法忘记了害一个早上的教训啊 源码 下面的源码介绍cline端基于多线程将送收消息分离 service端不绑定特定IP实现接收并回发消息。 udb_socket简单聊天室源码NetworkProgramming · 逆光/Linux - 码云 - 开源中国 (gitee.com) 二基于tcp协议编程
- listen——服务端监听 功能listen接口是用于创建一个被动的套接字用于监听传入的连接请求的接口。当一个套接字调用listen接口后它将开始接受传入的连接请求并将这些请求排队等待被接受或拒绝。就像一个饭店的外面的拉客人 sockfd监听用的套接字 backlog: 指定在拒绝新连接之前操作系统可以排队等待的最大连接数量。 返回值0成功-1失败。 2. accept——服务端接收 功能accept()函数会在sockfd套接字上接受一个传入的连接请求阻塞式接收并返回一个新的套接字描述符用于和客户端进行通信。同时addr和addrlen参数会被填充上客户端的地址信息。 //1. 接受请求struct sockaddrin send; //请求方信息bzero(send, sizeof send);socklent len sizeof send;// accept会等待请求方申请会处于阻塞状态int actual_socket accept(listensocket, (sockaddr)send_, len);if ( actual_socket 0 ){Logmessage(FATIL, accept fail%d %s, errno, strerror(errno));continue;} 3. connect——客户端请求 在调用 connect() 函数后系统会尝试连接到指定的服务器地址。多客户端向服务端进行连接 成功返回值为0如果连接失败返回值为-1并且可以通过 errno 变量获取具体的错误信息。 // 1.保留目标信息struct sockaddr_in goal_service;bzero(goal_service, sizeof goal_service);goal_service.sin_family AF_INET;goal_service.sin_port htons(atoi(args[2]));goal_service.sin_addr.s_addr inet_addr(args[1]);// 2.建立连接if (connect(cline_socket, (sockaddr)goal_service, sizeof goal_service) 0){Logmessage(FATIL, cline connect fail %d %s, errno, strerror(errno));exit(1);} 4. send recev 功能 send()函数将数据从buf缓冲区发送到已连接的套接字或者未连接的套接字(后者的UDP多用sendto) sockfd要发送数据的套接字描述符。flags传递给send()函数的标志参数通常为0返回值成功返回字节数失败-1 功能recv()函数会阻塞程序直到接收到足够的数据或发生错误。 sockfd指定要接收数据的套接字描述符。 flags指定接收数据的附加选项通常为0。 返回值成功字节数0连接关闭异常-1。 三基于TCP协议实现的线程池的服务端对客户端进行相互通信小项目 结构图一览 我的体会客户端以及服务端的设计在UDP设计中基本已经写过了TCP只是有一些小改动然后就是线程池也是直接使用了前面我们所写的线程池小项目总体来说考验我们的代码整合能力吧。 源码 线程池小项目Tcp_NetworkProgramming · 逆光/Linux - 码云 - 开源中国 (gitee.com) 有人会说万一我不想用线程池来实现服务端处理客户端的请求呢而是使用一些比较小型的呢答有而且不止几种 首先我们为什么要用线程池这个结构 答: 服务端不能一次只接受一个客户端的请求所以需要其他结构(子进程或多线程)来满足客户端的服务主线程只要接收请求分配任务即可。 服务端处理客户端请求方法——由简到密
- 单进程处理 void start(){signal(SIGCHLD, SIG_IGN);//循环接受信息while (1){//1. 接受请求struct sockaddrin send; //请求方信息bzero(send, sizeof send);socklent len sizeof send;// accept会等待请求方申请会处于阻塞状态int actual_socket accept(listensocket, (sockaddr)send_, len);if ( actual_socket 0 ){Logmessage(FATIL, accept fail%d %s, errno, strerror(errno));continue;}// 连接成功std::string send_ip inetntoa(send.sin_addr);uint16_t sendport ntohs(send.sin_port);Logmessage(NOWAIN, 连接成功,客户端为 ip:%s 端口号%d, send_ip.c_str(), send_port);// (1.0)服务器处理信息——单进程版本// //2. 分析处理数据server_dispose(actual_socket, send_ip, send_port); 缺点无法满足服务器多客户端连接 2. 子进程处理 // 连接成功std::string send_ip inetntoa(send.sin_addr);uint16_t sendport ntohs(send.sin_port);Logmessage(NOWAIN, 连接成功,客户端为 ip:%s 端口号%d, send_ip.c_str(), send_port);// (2.0) 优化——子进程版本pid_t pd fork();if (pd 0){//2. 分析处理数据close(listensocket); //子进程拷贝一份父进程的文件描述服表server_dispose(actual_socket, send_ip, send_port);exit(0);}close(actual_socket); // 子进程里保留了该文件描述符父进程已经不需要了// 按照曾经的理解现在应该让父进程进行等待子进程但多少都存在些问题。// 1. waitpid阻塞式等待不就跟单线程一样// 2. 非阻塞式等待需要构建子进程管理结构比较麻烦而且我们不需要关心子进程的返回情况。// 因此我们可以采用信号知识忽略子进程返回。// 操作细则在service启动时 signal(SIGCHLD, SIG_IGN); 2.1. 孙子进程处理 // 连接成功std::string send_ip inetntoa(send.sin_addr);uint16_t sendport ntohs(send.sin_port);Logmessage(NOWAIN, 连接成功,客户端为 ip:%s 端口号%d, send_ip.c_str(), send_port);// (2.1) ———— 子进程退出孙子进程让1接管pid_t pd fork();if (pd 0){//2. 分析处理数据close(listensocket); //子进程拷贝一份父进程的文件描述服表if (fork() 0) exit(0); // 孙子进程变成孤儿进程让bash接管server_dispose(actual_socket, send_ip, send_port);exit(0);}waitpid(pd, nullptr, 0); // 子进程进入立马退出父进程几乎不阻塞等待 缺点虽然满足了服务端可以同时满足多个客户端连接但是进程的创建会比较大的开销 。 3. 多线程处理 static void pth_service(void* args){PthreadData* data static_castPthreadData(args);// 进来先剥离线程这样主线程不用等待返回pthread_detach(pthread_self());server_dispose(data-_actual_socket, data-_ip, data-_port);close(data-_actual_socket);delete data;return nullptr;}……….// 连接成功std::string send_ip inetntoa(send.sin_addr);uint16_t sendport ntohs(send.sin_port);Logmessage(NOWAIN, 连接成功,客户端为 ip:%s 端口号%d, send_ip.c_str(), send_port);// (3.0) ———— 多线程版本pthread_t it -1; // 线程的标识号先默认为1后面在设置。PthreadData data new PthreadData;data-_ip send_ip;data-_port send_port;data-_actual_socket actual_socket;pthread_create(it, nullptr, pth_service, (void)data); 缺点1. 没有设置最大线程数在高压情况下有可能会导致service服务崩溃。2. 短时间内大量请求线程开辟消耗比较大的资源。 4. 线程池处理 // 连接成功std::string send_ip inetntoa(send.sin_addr);uint16_t sendport ntohs(send.sin_port);Logmessage(NOWAIN, 连接成功,客户端为 ip:%s 端口号%d, send_ip.c_str(), send_port);// (4.0) ———— 启用线程池// 让线程来进行对网络端的信息进行处理Task_add task new Task_add(actual_socket, send_port, send_ip);_thr_pool-push(task);// 交换策略服务端未被占满时来一条就交换任务队列if (_thr_pool-Get_queue_task_size() 0 _thr_pool-Get_queue_task_reserver_size() ! 0){_thr_pool-swap_queue();} 功能基本上没什么问题了但我们在客户端处理逻辑上是循环意味着该线程不会退出也就是长连接。意味着客户端的最大连接数就是线程池的数量如果客户端逻辑是短连接就不会出现线程池一直占满的情况了。 以上的编程是我们在应用层使用的编码往后我们将向下深入理解网络理解。 下期TCP协议原理 结语 本小节就到这里了感谢小伙伴的浏览如果有什么建议欢迎在评论区评论如果给小伙伴带来一些收获请留下你的小赞你的点赞和关注将会成为博主创作的动力
- 上一篇: php网站开发源码做网站怎么赚钱 111
- 下一篇: php网站开发招聘wordpress文章归档页面
相关文章
-
php网站开发源码做网站怎么赚钱 111
php网站开发源码做网站怎么赚钱 111
- 站长
- 2026年02月17日
-
php网站开发语言的优点收费网站解决方案
php网站开发语言的优点收费网站解决方案
- 站长
- 2026年02月17日
-
php网站开发与维护职位要求37网页游戏平台官网
php网站开发与维护职位要求37网页游戏平台官网
- 站长
- 2026年02月17日
-
php网站开发招聘wordpress文章归档页面
php网站开发招聘wordpress文章归档页面
- 站长
- 2026年02月17日
-
php网站开发总结文档建e网全景图合成教程
php网站开发总结文档建e网全景图合成教程
- 站长
- 2026年02月17日
-
php网站免费模板深圳定制西装哪家好
php网站免费模板深圳定制西装哪家好
- 站长
- 2026年02月17日

