保健励志美文体育育儿作文
投稿投诉
作文动态
热点娱乐
育儿情感
教程科技
体育养生
教案探索
美文旅游
财经日志
励志范文
论文时尚
保健游戏
护肤业界

多人在线游戏架构实战阻塞式网络编程

  课程简介
  本书主要讲述大型多人在线游戏开发的框架与编程实践,以实际例子来介绍从无到有地制作网络游戏框架的完整过程,让读者了解网络游戏制作中的所有细节。全书共12章,从网络游戏的底层网络编程开始,逐步引导读者学习网络游戏开发的各个步骤。
  本书通过近50个真实示例、近80个流程图,以直观的方式阐述和还原游戏制作的全过程,涵盖了网络游戏设计的核心概念和实现,包括游戏主循环、线程、Actor模式、定时器、对象池、组件编码、架构层的解耦等。
  本书既可以作为网络游戏行业从业人员的编程指南,也可以作为大学计算机相关专业网络游戏开发课程的参考书。
  关键词:网络游戏,游戏程序,程序设计
  1。1节介绍了单机游戏与网络游戏的区别,1。2和1。3小节带你理解IP地址和TCPIP。
  课程完整版可前往UWA学堂观看《多人在线游戏架构实战:基于C的分布式游戏编程》
  https:edu。uwa4d。comcourseintro03821。4阻塞式网络编程
  下面就从简单的网络模型入手来实现一个简单的网络程序。要达到的目的如下:
  (1)客户端与服务端建立网络通信。
  (2)完成通信之后,客户端向服务端发起一条协议。
  (3)服务端收到协议,并转发给客户端。
  (4)客户端收到协议,打印出来。
  在这个例子中,将展示网络编程的基本功能接收和发送,处理服务端与客户端对于Socket的不同表现,实现服务端与客户端的收发协议流程。1。4。1工程源代码
  该工程的源代码在本书源代码库的0101networkfirst目录下。先来执行工程,看看结果如何(注:在不少中文版的集成开发环境中把英文版中的Project翻译成项目,因此工程和项目在这种语境下指同一个概念,例如工程文件就是指项目文件)。工程中提供了两种打开方式,一种是在Windows系统下的VisualStudio工程文件,另一种是在Linux系统下的CMake文件。如果读者还不了解CMakeLists。txt文件的定义,那么建议先阅读附录中的CMake部分。本书提供的所有源代码均有这两种打开方式。
  如果在使用Windows编译源代码时出现SDK版本不一致的问题,那么右击解决方案,选择重定解决方案目标。产生这个问题的原因是工程原来指定的SDK与本地环境中的SDK版本不一致。再次提醒,编译目标为debug,x86。
  现在看看在Linux上如何执行本例。进入工程目录,执行脚本makeall。sh,编译的步骤已经在这个脚本中写好了,本书所有的工程都采用该方式编译。〔rootlocalhost0101networkfirst〕。makeall。sh
  执行makeall脚本时,它会将该工程上的所有可执行程序都进行编译,本例中生成了两个文件:clientd和serverd。为了便于调试,所有的库文件源代码都是直接编译到执行文件中的,不再生成中间的静态库文件。
  这是我们第一次使用makeall。sh脚本,每个工程都会有该脚本,用于批量编译。读者可使用vim。makeall。sh命令查看该脚本。
  这里做一个简短的说明,在makeall。sh脚本中提供了两个参数,默认情况下,采用Debug模式编译代码,如果执行命令。makeall。shrelease,就编译Release版本。除此之外,还可给定clean参数,即执行。makeall。shclean,目的是清除CMake生成的临时文件,重新生成Makefile文件。
  在脚本中提供了一个build函数,该函数的目的是对给定目录下的所有工程进行编译。以srclibs目录为例,函数build对libs目录下的srclibsnetwork目录进行了编译。这个目录是网络库工程,其下有一个已经写好的CMakeLists。txt文件。该文件与附录中讨论的文件格式大同小异,有3个地方值得注意。
  (1)编译文件名set(MyProjectNamenetworkd)
  指定一个编译文件名。当属性CMAKEBUILDTYPE为Debug时,输出文件加了d字符,以方便区分Debug和Release版本。CMake提供的STREQUAL函数用于字符串比较。
  (2)输出目录set(CMAKEARCHIVEOUTPUTDIRECTORY。。。。。。libs)
  设置属性CMAKEARCHIVEOUTPUTDIRECTORY。该属性指定了静态库生成的目录。
  工程生成的可执行文件放在工程目录下的bin目录中,库文件放在工程目录下的lib目录中。不论是Windows系统还是Linux系统都遵从该规则。
  (3)生成文件
  在CMakeLists。txt文件的最后使用了addlibrary指令,而不是addexecutable指令。addlibrary({MyProjectName}STATIC{SRCS})
  addexecutable生成可执行文件,addlibrary则生成一个库。关键字STATIC表示要生成一个静态库,需要生成动态库时,关键字改为SHARED即可。
  下面看看第一个例子的执行结果,执行makeall。sh编译完成之后,进入bin目录。〔rootlocalhost0101networkfirst〕cdbin〔rootlocalhostbin〕lsclientdserverd
  在bin目录下生成了serverd和clientd两个可执行文件。先运行serverd,再运行clientd。
  在表12中展示了服务端和客户端的打印数据。进程serverd开始运行之后,就会进入网络监听状态,当clientd启动后,serverd收到一个连接请求,打印acceptoneconnection,双方连接成功之后,clientd首先发出数据ping,serverd收到之后返回一条相同的数据,最后clientd收到serverd发出的数据。这个简单的例子完成了一个来回的数据发送与处理。看看流程图可能会更容易厘清思路,如图18所示,图中标注了数据流转的4个步骤。
  表12阻塞式网络通信运行结果
  客户端发送ping数据。
  服务端收到ping数据。
  服务端收到ping数据的同时返回一个ping给客户端。
  客户端收到ping数据。
  图18阻塞式网络通信流程
  网络监听和连接是如何实现的呢?无论是服务端还是客户端,首先要做的事情都是创建一个Socket(套接字)。那么Socket是什么呢?下面通过代码分析来简要说明。1。4。2服务端代码分析
  服务端的主要代码在server。cpp文件中。对比源代码进行查看,需要掌握以下几个关键点。
  关键点1:Socket初始化
  代码的第一行为创建Socket做初始化准备:sockinit();
  首先要了解什么是Socket。简单来说,Socket定义了IP地址上的一个通信连接。例如,同一台计算机向同一个服务端发起两个网络连接,这就是两个通信连接,不论在客户端还是服务端都会产生两个不同的Socket。Socket实际上就是一个ID,也可以用通道来理解这种通信。打个比方,你有一个手机号码,当你打电话给别人的时候,你与对方建立了一个通信通道。Socket也是类似的,每次通信开始,通信双方建立了Socket,这个Socket被分配了一个ID,一个固定的ID固定了通道,避免收到错误消息。
  sockinit()定义在network工程的network。h文件中。在Windows系统下的宏定义为:definesockinit(){WSADATAwsaData;WSAStartup(MAKEWORD(2,2),wsaData);}
  在Windows系统下,需要初始化执行WSAStartup函数。在Linux系统下,调用::socket函数之前不需要执行任何操作,所以定义了一个空宏。
  关键点2:创建Socket
  初始化操作完成之后需要创建一个Socket。创建失败会调用宏sockerr来显示其错误。创建代码如下:SOCKETsocket::socket(AFINET,SOCKSTREAM,IPPROTOTCP);if(socketINVALIDSOCKET){std::cout::socketfailed。err:sockerr()std::endl;return1;}
  函数::socket是底层函数,这个函数调用的细节放在后面来讲解。它在两个系统下略有不同。在Linux系统下,位于usrincludesyssocket。h文件中,其定义如下:externintsocket(intdomain,inttype,intprotocol)THROW;
  从函数返回值可以看出,生成的Socket为int类型。
  而在Windows系统下,返回值为SOCKET类型。socket()函数定义如下:SOCKETWSAAPIsocket(Inintaf,Ininttype,Inintprotocol);typedefUINTPTRSOCKET;
  在Windows系统下,SOCKET类型被重定义为一个UINT类型,也就是说,如果编译的版本为32位,SOCKET类型就为unsignedint,64位则为unsignedint64,总之,SOCKET本身也是一个数值类型。
  为了兼容Linux和Windows这两个系统,工程中在Linux下定义了两个宏:SOCKET和INVALIDSOCKET。defineSOCKETintdefineINVALIDSOCKET1
  虽然两个系统中的定义略有不同,但::socket函数的表现却是相同的。如果调用::socket函数失败,在Linux系统下的返回值为1,在Windows系统下返回一个宏定义INVALIDSOCKET。
  除了定义不同之外,两个系统显示出错信息的函数也有差别,工程中定义了sockerr宏来处理。关于这个宏,在Windows系统和Linux系统下的定义不同,其定义如下:ifndefWIN32definesockerr()WSAGetLastError()elsedefinesockerr()errnoendif
  关键点3:绑定IP与端口
  创建Socket之后需要指定IP地址和端口实现绑定操作,本例中指向了本机127。0。0。1的2233端口。sockaddrinaddr;memset(addr,0,sizeof(sockaddrin));addr。sinfamilyAFINET;addr。sinporthtons(2233);::inetpton(AFINET,127。0。0。1,addr。sinaddr。saddr);if(::bind(socket,reinterpretcastsockaddr(addr),sizeof(addr))0){std::cout::bindfailed。err:sockerr()std::endl;return1;}
  在绑定过程中使用了sockaddrin结构,该结构中指定了协议族、IP地址和端口。
  之前讨论过IP地址可以唯一标识一台计算机,但一台计算机可能有多个IP地址,至少可以有一个对外的地址和一个对内的地址。日常中,设置IP地址为192。168。0。120,这是一个内网地址,127。0。0。1是一个特定的描述,指向本机,也是一个内网地址。在本例中,打开127。0。0。1的2233端口,开放的范围只是本机,也就是说这个服务端只能由本机上执行的clientd对它进行连接。如果这里填写的IP地址是192。168。0。120,那么开放的范围是整个局域网,离开了局域网就不能访问了。如果计算机还有一个公网IP地址,调用::bind函数绑定的是一个公网IP地址,那么在任何地方、任何计算机上都可以访问这个IP地址开放的端口。
  特别说明:如果在Linux下反复测试时遇到了错误::bindfailed。Err:98,则是因为之前绑定的端口没有被释放,系统有一定的回收时间。为了快速释放,我们可以输入sslnpt命令找到端口对应的PID,使用kill指令杀掉进程。〔rootlocalhostbin〕sslnptStateRecvQSendQLocalAddress:PortPeerAddress:PortLISTEN010127。0。0。1:2233:users:((logind,pid6367,fd3))〔rootlocalhostbin〕kill96367
  关键点4:监听网络
  绑定好IP地址和端口之后,还需要打开对Socket的监听,服务端的工作才算完成。其代码如下:intbacklogGetListenBacklog();if(::listen(socket,backlog)0){std::cout::listenfailed。sockerr()std::endl;return1;}
  对于服务器来说,这是必不可少的一步,调用了底层函数::listen。只有打开了监听,我们才可以敏锐地察觉是否有客户端对该端口发起了通信请求。参数backlog指定了请求缓存列表可以有多长。
  关键点5:等待连接
  有了监听就可以接收连接了,接收连接的代码如下:structsockaddrsocketClient;socklentsocketLengthsizeof(socketClient);intnewSocket::accept(socket,socketClient,socketLength);
  在本例中,程序会在::accept函数阻塞住。如果在::accept后面一行打一个断点,会发现断点不会被触发。::accept函数的功能是接收一个请求,如果没有就会一直等待。所以,在运行了serverd还没有运行clientd之前,服务端处于阻塞状态,它在等待一个连接请求。
  在一些网络编程图书中会讨论TCP的3次握手,在本程序中,我们并没有看到3次握手,而是通过::accept函数就收到了连接。这并不是说3次握手不存在或者没有完成,而是这3次握手过程已经在底层完成了。
  关键点6:接收数据
  当::accept函数接收到有新的连接到来时,双方通信建立完成,可以开始发送数据。代码中调用了底层::recv函数接收数据,再调用::send函数发送接收到的数据。这部分的代码如下:charbuf〔1024〕;memset(buf,0,sizeof(buf));autosize::recv(newSocket,buf,sizeof(buf),0);if(size0){std::cout::recv。bufstd::endl;::send(newSocket,buf,size,0);std::cout::send。bufstd::endl;}
  在上面的代码中,接收数据放在一个长度为1024字节的缓存中,接收到什么数据就发送什么数据回去。
  关键点7:关闭Socket
  关闭Socket调用了两个宏:sockclose(socket);sockexit();
  在Windows和Linux系统下做了不同的处理。在Windows系统下初始化时调用了WSAStartup函数,结束时则需要调用WSACleanup函数。宏定义如下:ifndefWIN32definesockexit()definesockclose(sockfd)::close(sockfd)elsedefinesockexit(){WSACleanup();}definesockclose(sockfd)::closesocket(sockfd)endif
  特别说明:在Linux下关闭Socket时,有时使用::close函数,有时使用::shutdown函数。这两者有什么区别呢?
  可以做一个实验,将::close函数替换为::shutdown函数。在生成和关闭Socket处进行打印,从打印信息中可以看出,使用::shutdown函数,关闭过的Socket即使关闭了,也不会重用。每次有新的连接到来时,就需要用到新的Socket,其值会在之前的值上加1。这是因为::shutdown函数会关闭TCP连接,但不释放Socket。而::close函数会将套接字计数减1,当计数0时,会自动调用::shutdown函数。看上去在关闭连接时使用::close才是正确的,但为什么还是有人直接使用::shutdown呢?因为使用::close并不能真正断开连接,它只是计数减1,在某些情况下,可能需要直接断开连接,所以调用::shutdown函数关闭网络。
  而使用::close函数,在某些情况下,Socket的状态会变为CLOSEWAIT状态,CLOSEWAIT实际上就是等待关闭状态。
  出现这种情况的原因比较复杂,有一种情况是客户端想关闭,但服务端可能还在读或写,就产生了等待。在网络编程中,这是我们需要特别注意的一个问题。1。4。3客户端代码分析
  客户端的源代码与服务端略有不同,相对来说步骤简单一些。客户端的主要逻辑在client。cpp文件中,需要掌握以下几个关键点。
  关键点1:Socket初始化
  在客户端开始时,同样初始化和创建了Socket,与服务端原理一致。sockinit();SOCKETsocket::socket(AFINET,SOCKSTREAM,IPPROTOTCP);if(socketINVALIDSOCKET){std::cout::socketfailed。err:sockerr()std::endl;return1;}
  关键点2:网络连接
  对于客户端来说,并不需要执行::bind绑定函数,也不需要监听端口。客户端需要执行的是调用::connect函数,它向一个指定的IP和端口发起连接操作。函数::connect会用到sockaddrin结构。调用代码如下:sockaddrinaddr;memset(addr,0,sizeof(sockaddrin));addr。sinfamilyAFINET;addr。sinporthtons(2233);::inetpton(AFINET,127。0。0。1,addr。sinaddr。saddr);if(::connect(socket,(structsockaddr)addr,sizeof(sockaddr))0){std::cout::connectfailed。err:sockerr()std::endl;return1;}
  在客户端,使用sockaddrin结构的初始化工作与服务端一样。客户端调用了服务端没有涉及的底层函数::connect,向一个指定的地址(也就是在服务端开放的地址)发起了一个连接。
  关键点3:发送数据
  客户端与服务端一致,都是调用底层函数::send发送数据。使用下面的代码发送一个ping字符串:std::stringmsgping;::send(socket,msg。cstr(),msg。length(),0);
  关键点4:接收数据
  客户端发送数据之后,陷入等待操作中,函数::recv等待接收数据。charbuffer〔1024〕;memset(buffer,0,sizeof(buffer));::recv(socket,buffer,sizeof(buffer),0);std::cout::recv。bufferstd::endl;1。4。4系统差异
  在前两小节中,对Linux和Windows两个系统进行了有区别的编码。除了Socket的定义之外,还有两个大的区别:
  (1)虽然网络API是底层函数,但在Windows系统下创建Socket之前需要调用WSAStartup函数,而退出的时候需要调用WSACleanup函数。两个函数的定义如下:intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);intWSACleanup();
  (2)获取错误的方式也略有不同。在Linux系统下使用errno变量,在Windows下使用WSAGetLastError函数,如果执行网络API时出错,该函数就会返回一个错误码,定义如下:intWSAGetLastError();1。4。5网络底层函数说明
  前面举了一个简单的例子,用到的底层函数是网络编程的基础,本书之后的所有示例都是基于这些网络底层函数来完成的。为了加深理解,下面对这些底层函数逐一进行详细的说明。
  1。函数::socket
  客户端与服务端在初始化时,均使用了::socket函数。每个网络通信必有一个Socket。函数的参数说明见表13,原型如下:intsocket(intfamily,inttype,intprotocol);
  表13socket函数参数
  在本节的例子中,不论是在服务端还是客户端,生成Socket时均采用了AFINET、SOCKSTREAM、IPPROTOTCP这3个参数,即采用IPv4协议,以SOCKSTREAM数据流发送时采用可靠的TCP。
  正常情况下,调用该函数会返回一个大于零的正数,即Socket值。这个值是唯一的,由系统分配。如果A与B建立了连接,那么对于A来说,在连接没有中断的情况下,它一定是一个定值,且不与其他Socket值相同。Socket这个单词在英文里的翻译是插槽、插座,在网络术语中一般翻译成套接字,可以将其理解为如果占用了一个插槽,其他人是不可能再使用的。
  在Windows下,生成的Socket值是随机大于1000的值,在Linux下,它是从个位数开始累计的。在Linux下,Socket值也被称为描述符。这和Linux的内核结构有关联,这里不需要深究,只需要知道Socket也称为描述符即可。一旦Socket创建成功,返回的Socket值就会成为网络通信的重要依据。需要注意的是,Socket值是可以被复用的,也就是说,如果最开始分配了123给A,随后A断线,C上线,C也有可能分配到123。
  2。函数::bind
  ::bind是服务端必不可少的一个函数,其作用是指定IP和端口开放给客户端连接,客户端则没必要调用该函数。函数的参数说明见表14,函数的原型如下:intbind(intsockfd,constsockaddraddress,intaddresslen);
  表14bind函数参数
  参数sockfd即调用::socket函数之后得到的Socket值。
  sockaddr是通用的套接字地址结构,在代码中还使用了sockaddrin结构,这两者在这里没有什么差别,长度一样,可以相互转换,sockaddrin是Internet环境下套接字的地址形式。参数address指定了Socket需要绑定的地址信息,这些信息中包括IP和端口。
  该函数返回负数就表示出错了。如果试图绑定一个已经在使用的端口,调用::bind就会失败。
  3。函数::listen
  ::listen是服务端调用的函数,用于对IP地址和端口的监听。函数的参数说明见表15,函数的原型如下:intlisten(intsockfd,intbacklog);
  表15listen函数的参数说明
  关于连接队列的最大长度,可以使用系统的宏SOMAXCONN。在Linux下,它的定义在usrincludebitssocket。h文件中,默认为128。值backlog的意义在于,当一个连接请求到来时,另一个连接请求可能同时到来,系统需要缓存其中之一,backlog是系统处理连接的缓冲队列的长度。虽然TCP有3次握手,但是目前来看这个过程还是相当快的,所以510个缓存已经足够使用。
  该函数返回负数就表示出错了。
  4。函数::connect
  ::connect是对一个已知地址进行网络连接的函数。一旦客户端调用::connect函数,就会触发TCP的3次握手协议,3次握手完成之后,在服务端会调用::accept函数。
  在调用::connect函数时,如果失败,就不能对当前Socket再次调用::connect函数,正确的做法是关闭Socket再次调用::connect函数。该函数的参数与::bind函数是一致的。函数的原型如下:intconnect(intsockfd,constsockaddraddress,intaddresslen);
  该函数返回负数就表示出错了。
  5。函数::accept
  该函数用于监听端口,若::accept收到数据,则一定有一个新的连接被发起。函数的参数与::bind函数是一致的。函数的原型如下:intaccept(intsockfd,sockaddraddress,intaddresslen);
  函数::accept返回的值是一个新的Socket值。调用::accept时,我们传入了一个Socket值,这个值可以称为监听Socket,而返回的这个新值就是客户端连接服务端的连接Socket。这两个值是有区别的。服务端有且仅有一个监听Socket,却可以有无数个连接Socket。
  6。函数::send和::recv
  函数::send和::recv是一对用于发送和接收数据的函数,除了这两个函数之外,网络底层还提供了其他发送和接收数据的函数,适用于不同的场合,这里只介绍我们使用的这一对函数。函数的参数说明见表16,函数的原型如下:intsend(intsockfd,constcharbuf,intlen,intflags)intrecv(intsockfd,charbuf,intlen,intflags)
  表16发送、接收函数参数
  在4个参数中,需要着重说明的是buf参数。对于::send函数而言,发送的缓冲buf是const指针,而len则是发送数据的长度。
  对于::recv函数而言,buf是接收数据的缓存,len是该缓存的长度。假设服务端向客户端发送了2024字节的数据,但客户端接收buf的长度只有1024,len的长度也只能为1024,即::recv函数一次只会读取系统底层网络缓冲中的1024字节,放入buf缓冲中。这个概念非常关键,会引发粘包、拆包的问题。网络数据并不是我们想象中一条一条规整地发送过来的,有可能接收的1024字节里面有3个协议数据,也有可能接收的1024字节只是某个协议的一部分,需要多次读取。在后面的例子中,我们会详细讲解这些情况该如何处理。
  发送和接收函数调用失败返回非正数,若成功,则返回发送、接收的字节长度。对于::recv函数来说,若返回0,则表示在另一端发送了一个FIN结束包,网络已中断。但::recv函数在返回负数时,也并不都意味着网络出错而需要断开网络,这在后面用到的时候再讲解。1。4。6小结
  我们已经对网络通信有了一定的了解,客户端和服务端在初始化时略有不同,但收发数据的流程是相同的,本例采用了阻塞式的收发数据方式,所有的代码都是在阻塞模式下进行的。函数::accept、::send和::recv都处于阻塞模式下。
  所谓阻塞,就是一定要收到数据之后,后面的操作才会继续。客户端调用::connect函数连接到服务端,发送数据之后一直阻塞在::recv函数上,直到收到服务端传来的数据才退出。服务端同样是阻塞的,在::accept函数处等待连接进来,如果没有就一直等待,接收到一个连接之后,再次阻塞,等待::recv函数返回数据。
  作为服务端,采用阻塞模式显然不够高效。一般来说,服务端需要同时处理成千上万个通信,不能因为一个连接而阻塞另一个连接的收发数据进程。在实际情况下,更常用的是非阻塞模式。接下来以一个实例来说明非阻塞模式是如何工作的。
  课程完整版可前往UWA学堂观看《多人在线游戏架构实战:基于C的分布式游戏编程》
  https:edu。uwa4d。comcourseintro0382本书特色
  1、从网络游戏的底层编码开始,深入讲解游戏开发的详细步骤、游戏主循环、线程的使用、Actor模式的应用等。
  2、以直观的方式阐述和还原游戏制作的全过程,全面介绍游戏编码过程中众多的核心概念和具体实现,如定时器、对象池、组件编码、架构层的解耦等。
  3、使用C来实现游戏的架构,读者也可以举一反三,使用其他的编程语言轻松实现游戏开发目标。你将获得
  1、充分了解业务逻辑和底层框架的设计意图
  2、立足实践的服务端学习思路,深入浅出
  3、用实际案例贯穿各知识点,在实践中学习
  4、了解商业游戏的设计思路和实现方法

杨卫兵的水性漆成功用在冬奥会上2022年3月10日,唐山市清华大学校友会校友、易元(迁安)新材料科技有限公司董事长杨卫兵来校友会介绍了他们生产的工业水性漆成功用在冬奥会上。杨卫兵自2003年开始在北京……高中作文回头看看你的母亲在漫漫人生之旅中,你要走过无数的艰难险阻,当你准备就绪急切期盼启程的时候,请记住,在你的背后,请你回头看一眼你的母亲,哪怕就这一眼,也会让她心满意足。一位女作家曾写过这样……重新确定主教练!约书亚将与罗伯特加西亚合作,期待复仇乌西克据ESPN报道,前世界重量级拳王安东尼约书亚,已经重新确定了主教练人选,他将与美国名帅罗伯特加西亚合作,希望在对方的指导下复仇奥雷科桑德乌西克。去年9月,约书亚在英国主场……天睛了真好作文范文天晴了,真好!灿烂的阳光照耀在我心上,将之前的那些疑惑和阴霾全部一扫而光。对于竹笛,我有一种特别的爱好,那是我心中最美妙的声音。我学习竹笛已经有一段时间了,指法和技……平等待人优秀作文有时候我想了很多很多,原来平等待人也是一件那么值得去学习的事,但是我们身边的人呢?总是以貌取人,以一个人的优良品质成绩来对待这个人,就连有些大人们也是这样,它们看不起那些长的丑……我读经典,我荐书在暑假里我读了一本书,叫作《老人与海》。这本书值得推荐给大家。书里的文字看似简单,却有着惊人的表现力,而且极其准确。《老人与海》讲述了一个老人在海上一个人钓鱼时捕到了一条……想不到吧?绿军主帅球员时期曾和库里交手6次,他们的表现如何?凯尔特人昨天在客场4分险胜热火队,时隔12年后再次杀进总决赛,他们这一路走来并不容易。本赛季是乌度卡执教凯尔特人的首个赛季,作为一个菜鸟教练,赛季初他并没能带领凯尔特人队打出预……法网男单下半区乱了,2大世界前4种子爆冷出局,争冠形势却明朗北京时间5月31日凌晨,2022年法网结束了第9比赛日争夺,这个比赛日之后,男女单打八强全部诞生,随之而来的14决赛对阵都确定下来,男单方面:德约科维奇纳达尔,兹维列夫阿尔卡拉……二月二龙抬头的传说与习俗农历二月初二,古称ldquo;春龙节rdquo;、ldquo;龙头节rdquo;,传说是ldquo;龙抬头rdquo;的日子,它是古代民间极为盛行的节日,其中的许多习俗一直延续……凌晨0点!克洛普最新表态引爆争议,曼联球迷吐槽输不起就辞职北京时间5月30日凌晨0点,针对欧冠决赛的比赛,利物浦主帅克洛普接受接受《BTSport》采访时给出了自己的看法,他表示在对手一支收缩防守时,无法能踢出一场完美的比赛,在刚刚丢……要相信孩子读书笔记要相信孩子读书笔记1教师,甚至学校之所以对个别学生无能为力,其原因并不在于学生是不可救药的,而在于指导整个教育过程的方针是错误的。教师往往只致力于纠正缺点,最多是预防缺点……春天冬天过去了,我们又迎来了美丽的春天。春天真美啊!河边的柳树姑娘起床了,她伸了伸懒腰,一阵微风吹过,柳树姑娘梳起了自己的长辫子,天上下起了蒙蒙细雨,好像在给柳树洗澡,雨停了……
给宝宝吹空调前,一定记得不要做这几件事夏天一到,要不要给娃吹空调,就成了爸妈们十分纠结的问题。吹吧,冻感冒了怎么办,还有网上时不时曝出的空调病、面瘫,孩子小,肯定更容易生病。可不吹空调吧,风扇的体验感实在一般……来一场舌尖上的旅行,九阳太空空气炸锅上手测评有人不爱旅游爱蜗居,不爱玩乐爱臭美,不爱抽烟爱喝酒,但美食却是无法抵抗的诱惑。嫌弃外面餐调料太多,油烟太重,完全可以自己在家中做美食。周末给全家人带来一场舌尖上的旅行,只要有这……国羽骚操作,身高设大门槛,这是打算将国羽连根拔起?国羽最近的骚操作是一波接一波,世锦赛男双的报名还悬而未决,国羽新星选材还规定了男队员身高不低于185,女队员不低于175。默默查了官方资料,林丹178,风云组合181、1……周冠宇极限操作!舒马赫之子车祸,法拉利太尴尬,勒克莱尔爆粗F1摩纳哥大奖赛在大雨中进行,这场比赛一波三折,因为大雨推迟1个多小时开始,第29圈车王之子米克舒马赫又打滑发生严重车祸导致比赛中断,导致最后阶段距离规定结束时间非常近,现场也……AQIRYS推出TGAALPHA游戏鼠标65g轻量化,搭载原近日,外设品牌AQIRYS推出全新的TGAALPHA系列无线游戏鼠标,从官方的鼠标的规格配置内容来看,该鼠标定位高端,而且已经被归入TheGreatAnnihilator高端鼠……即将开庭!车评人蔡老板被特斯拉起诉,曾爆料其工作人员吃拿卡要6月1日,特斯拉(上海)有限公司与蔡甲相关名誉权纠纷案将在浙江省宁波市中级人民法院开庭。蔡甲为拥有逾200万粉丝的网红车评人蔡老板,前不久他曾透露自己第二次收到特斯拉起诉……煎熬17年,这个国产操作系统却选择归0,中国院士太及时了国产操作系统一直以来是国人心心念念的梦想。从上个世纪90年代,芬兰人林纳斯托瓦兹发明了Linux操作系统,并且让Linux系统开源,可以人人免费使用,上个世纪末Linux进入到……更实惠的静听之选!聆听小米真无线降噪耳机3在推出小米真无线降噪耳机3Pro之后,小米又给消费者带来了小米真无线降噪耳机3。它相比前者最大的变化是不支持空间音频,但价格却便宜了200元左右,以覆盖有着不同需求的消费群体。……优秀作文我的课余生活450字我的课余生活像七色花一样丰富多彩,我喜欢旅游、游泳、打篮球、做手工可我最喜欢的还是看书。每次进城,我都要缠着爸爸去新华书店买书,因为那些书就像磁铁一样深深地吸引着我。回到……只要我们不自省,我们就不会进步古人云:仓禀实而知礼节,衣食足而知荣辱。但现在的现象却是衣食足而不知荣辱了。这几天的教科书插画事件引人深思,是文化入侵还是艺术的另一种特性风格。就算是艺术的另一种特性的风格,但……散落在流年里的记忆品学网专稿未经允许不得转载记得那时年纪小,你爱谈天我爱笑。有一回并肩坐在桃树下,风在树梢鸟在叫。不知怎么睡着了,梦里花落知多少。记得初见时,你是向日葵那……我从关怀中感受幸福初三作文世界上没有两片相同的树叶,即使在同一片蓝天下仰望星空,我们也自己主宰的世界里追逐着幸福与成功,所以每个人眼中都有不一样的幸福。在我看来,快乐就是最纯真的幸福,而简简单单的关怀就……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网