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

科技公司做网站如何制作一个网页页面

科技公司做网站,如何制作一个网页页面,php个人网站简洁,wordpress 图加载中其实有了UDP的基础,TCP不管怎么说学习起来都还是比较舒服的,至少是比直接就学习TCP的感觉好。 这篇文章最多就是介绍一下起手式,如果想带业务的话和UDP那篇是完全一样的,就不进行演示了。 总的来说还是很简单的。 目录 Echo服务端…

其实有了UDP的基础,TCP不管怎么说学习起来都还是比较舒服的,至少是比直接就学习TCP的感觉好。

这篇文章最多就是介绍一下起手式,如果想带业务的话和UDP那篇是完全一样的,就不进行演示了。
总的来说还是很简单的。

目录

  • Echo
    • 服务端起手式
    • 服务端LOOP
    • 客户端起手
    • 客户端LOOP
    • 验证
    • 改进
      • 方案一
      • 方案二
    • 验证

Echo

我们还是从最简单的不带业务的Echo开始。

服务端起手式

服务器起手式
首先要说明的一点是,TCP是面向字节流,有连接。
而UDP创建好套接字后不管连接,直接recvfrom,sendto就可以发送。

在TCP编码中会体现出有连接的特点,面向字节流会在理论中提及,代码中实践。


创建套接字
首先与UDP不同的是,UDP的第二个参数是SOCK_DGRAM

_listenfd = ::socket(AF_INET, SOCK_STREAM, 0);

关于这两个参数不同含义更详细的放在下图中了。
在这里插入图片描述
另外,这次使用listenfd接收,以前我们获得的就是sockfd,直接使用这个描述符进行收发,那么叫listenfd肯定是有特别用意。


进行bind
bind没什么好说的,仍旧是要注意填参问题。

int n = ::bind(_listenfd, (struct sockaddr *)&local, len);

进入listen状态

在这里插入图片描述

从这里就可以看到面向连接的痕迹了。
那么什么叫listen状态?
我们举一个小例子:
UDP就是无人售货店,不许用老板看店即可买东西。
但是TCP就是有人售货店,需要老板在才可以买东西,而TCP就是那个有人售货店,listen就是设置为老板模式,这样就可以接客了。

第一个参数就是你得到的listenfd。
第二个参数是连接队列长度,这个值我们暂时先不用管,一般默认设置为4, 8, 16即可,不需要太大。

n = ::listen(_listenfd, gbacklog);

服务端LOOP

accept
来了新的连接我们就要去accept了
换句话说就是在有人售货店中现在如果来客人了老板就需要去接客。

int sockfd = ::accept(_listenfd, (sockaddr *)&peer, &len);

参数是输出型参数,来一个连接就可以获得这个连接的基本信息。
但是要注意填参时一定要正确填参,虽然addrlen是一个输出型参数,但仍然需要正确初始化,不能不初始化。
我就犯了这个错误,导致有时错误(accept或者connect错误,connect在客户端会提到),甚至搞的我以为这是tcp特性…在这里插入图片描述
但是我们注意到返回值是一个文件描述符!?那么他是什么?与listenfd有何区别?在这里插入图片描述我们举一个例子进行理解:
在这里插入图片描述
上图可以形象的帮助理解返回值。
其中饭店 = 服务器
客户 = 新连接
揽客员 = listenfd(socket返回值)
服务员 = sockfd (accept返回值)

listenfd不直接提供服务,sockfd才直接提供服务!
所以在TCP服务端我们一般将socket返回值叫做监听套接字。

没有连接时就会陷入阻塞状态,accept失败返回-1(这里可以理解为揽客员都把路人拉到店里面,但是路人又临时有事离开了,导致拉客失败~)。


下段代码是TCP的框架代码,与UDP有很大的不同。

void Loop()
{_isrunning = true;while (_isrunning){sockaddr_in peer;socklen_t len = sizeof(peer);int sockfd = ::accept(_listenfd, (sockaddr *)&peer, &len);if (sockfd < 0){continue;}// version 0 :提供长服务。service(sockfd);}_isrunning = false;
}

与UDP有很大的不同:
每一次循环都对应着一个新连接,我们随后要对这个新连接进行长服务;
而UDP是不管来的是谁,都统一处理。


读写操作
我们在长服务中进行读写操作。

因为我们是面向字节流,而管道、文件也都是流。
且Linux下一切皆文件,管道、文件都是文件,所以都是可以用文件操作read,write进行读写,所以这里也可以使用文件操作!

void service(int sockfd)
{// 长服务while (true){char inbuffer[1024];int n = read(sockfd, inbuffer, sizeof(inbuffer) - 1);if (n > 0){inbuffer[n] = 0;int m = write(sockfd, inbuffer, n);if (m < 0){break;}}else if (n == 0){break;}else{break;}}::close(sockfd);
}

但是这里有一个细节要注意:read的返回值>0是表示读到的字节数(无\0),==0时表示读到文件结尾,在这里表示客户端结束。
就想吃在管道那里,写端管了,读端读出的自然都是0了。

客户端起手

socket

int sockfd = ::socket(AF_INET, SOCK_STREAM, 0);

注意客户端仍旧是用socket的返回值进行通信。


connect
同样,客户端还是不用bind,在UDP那是sendto时OS进行绑定,而在这就是connect时帮我们自动绑定。

sockaddr_in peer;
memset(&peer, 0, sizeof(peer));
inet_pton(AF_INET, ip.c_str(), &peer.sin_addr);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;
int n = ::connect(sockfd, (sockaddr *)&peer, sizeof(peer));

客户端LOOP

这里没啥好说的,就是普通的write + read。
但是要注意:由于是面向字节流,所以这里的处理是有问题的!具体如何操作请看用户自定义协议与序列化

while (true)
{std::cout << "Please enter#";std::string line;getline(std::cin, line);n = write(sockfd, line.c_str(), line.size());if (n < 0){break;}char inbuffer[1024];n = read(sockfd, inbuffer, sizeof(inbuffer) - 1);if (n > 0){inbuffer[n] = 0;std::cout << inbuffer << std::endl; }
}

完整代码链接

验证

在这里插入图片描述
但是当我们多开一个客户端就会发现:一个服务端只能服务一个客户端。
原因在于我们当前是串行,必须等当前客户端退出才能accept下一个客户端,并没有处理并发客户端的能力。

所以改进就来了

改进

方案一

多进程方案。
我们知道子进程是会继承父进程的代码和数据的,同样的文件描述符表也会继承,因此我们就可以利用这个特点让子进程去执行代码和数据。

在这里插入图片描述
首先我们fork之后就要将不需要的文件描述符关闭
对于子进程来说,是怕误操作;
对于父进程来说,是为了防止文件描述符泄露,因为进程具有独立性,当子进程继承了后,就与父进程相互不影响了。若是父进程不关闭,一直申请fd却步关闭那么就造成了资源泄露。

但是注意,由于父进程要进行等待,所以此时仍然是串行。
想要解决有两种方法

  1. 由于子进程结束时会发送SIGCHLD信号,于是进行信号忽略signal(SIGCHLD, SIG_IGN)另外这也是最佳方案
  2. 下段代码所示:我们进行再次fork,并让子进程退出,所以此时孙子进程成为了孤儿进程,孤儿进程的父进程是OS,结束归OS管,完美的利用了OS的特性。
pid_t pid = fork();
if (pid == 0)
{if (fork() > 0) exit(0);// 子进程关闭不需要的fd,防止误操作。::close(_listenfd);service(sockfd, inetaddr);exit(0);
}
waitpid(pid, nullptr, 0);
// 父进程关闭不需要的fd,防止内存泄漏。
::close(sockfd);

方案二

多线程
我们创建一个新线程,让新线程去执行service即可。

验证

此时同时启动两个客户端也可以完美的进行并发了。
在这里插入图片描述

http://www.15wanjia.com/news/21040.html

相关文章:

  • 建立网站第一步是什么seo搜索引擎优化工资多少钱
  • 给公司建立一个网站吗推广seo优化公司
  • 上海一 网站建设公司百度最新秒收录方法2021
  • 怎么跟客户介绍网站建设怎么做网页
  • 在国外社交网站做产品推广站长交流平台
  • 杭州拱墅网站建设关键词优化哪家强
  • 如何用asp做视频网站关键词网站
  • 济南软件网站建设域名收录查询工具
  • 织梦整形医院网站模板江苏seo平台
  • 计算机系毕设代做网站宁德市人社局官网
  • 哪些分类网站网上营销方法
  • 新乡哪有网站建设公司谷歌浏览器安卓下载
  • 怎么做存储网站湖南seo服务电话
  • 山东网站制作策划网店推广培训
  • 西安营销型网站建设动力无限个人网站模板建站
  • 做政府门户网站建设长沙优化网站推广
  • 群晖的网站开发宁波seo教学
  • 自己做网站背景图片宁波网站制作优化服务
  • 网站模板如何修改域名海外推广运营
  • 滨州网站建设铭盛信息上海哪家seo好
  • 手表网站大全百度获客平台怎么收费的
  • 宁夏住房和城乡建设厅网站首页重庆seo网站推广优化
  • 全球搜索引擎网站seo关键词排名优化软件怎么选
  • 建网站引流做淘宝网络推广靠谱吗
  • 做视频网站需要多大的带宽网络公司网站建设
  • 诸城做网站建设的网店营销策划方案范文
  • 只用html5做网站seo网站优化
  • 类似站酷的设计网站国家提供的免费网课平台
  • 两学一做 投稿网站网络推广公司可不可靠
  • 济南网站建设培训班全国疫情高峰感染高峰