当前位置: 首页 > 后端技术 > Node.js

Node.js学习之路10——创建TCP服务器

时间:2023-04-03 23:14:13 Node.js

1.创建一个TCP服务器letserver=net.createServer([options],[connectionListener]);createServer方法返回创建的TCP服务器options参数options参数值是一个对象,可以用来兑现一个boolean类型的allowHalfOpen属性,当为false时,当TCP服务器收到客户端发送的FIN包时,它将发回一个FIN数据包。当为真时,TCP服务器在收到客户端发送的FIN包后,不会再发回一个FIN包,这样TCP服务器可以继续向客户端发送数据,但不会继续接收客户端发送的数据客户端。必须调用end方法来关闭套接字连接。connectionListener参数用于指定在客户端和服务器建立时要调用的回调。function.constnet=require('net');letserver=net.createServer(false,function(socket){});2.建立连接当客户端与服务端建立连接时,会触发连接事件,我们可以通过连接事件监听,指定事件的返回函数方法来指定需要进行的处理当客户端与服务器建立连接时执行。server.on('connection',function(socket){})回调函数中的参数为TCP服务器监听的socket端口对象创建后,可以通过listen方法通知服务器开始监听客户端连接。指定了三个方法2.1Listen方法一:server.listen(port,[host],[backlog],[callback]);端口是必须指定的参数。当它为0时,会为TCP分配一个随机端口号。host为指定的需要监控的IP地址或主机名。如果省略,服务器将调用任何IPv4地址客户端连接积压是一个整数值,用于指定等待队列中的最大客户端连接数。一旦超过这个长度,TCP服务器就会开始拒绝新客户端的连接请求。该参数的默认值为511。对于TCP,服务器指定需要监听的地址和端口后,服务器会立即开始监听来自该地址和端口的客户端连接。此时会触发服务器的监听事件,可以使用listen方法的callback参数用于指定触发监听事件时调用的回调函数,回调函数中不使用任何参数。2.2监听方式二:server.listen(path,[callback]);这种形式的listen方法用于通知用户使用unix端口服务器开始监听来自该路径的客户端连接。path是要监视的指定路径。当使用unix端口的服务器指定要监听的路径时,服务器会立即开始监听来自该路径的客户端连接。此时会触发服务端的监听事件,可以通过listen方法的callback参数指定触发监听事件时调用的回调函数。回调函数不需要使用任何参数。2.3监听方法三:server.listen(handle,[callback]);这种形式的listen方法用于通知TCP服务器开始侦听具有指定套接字句柄的客户端进行连接。该方法使用两个参数(句柄可以是TCP服务器对象或文件描述符,在WINDOWS操作系统中不支持对文件描述符的监听)第一个参数用于执行需要监听的socket句柄。当为TCP服务器指定需要监听的套接字句柄时,服务器会立即从套接字句柄开始监听当服务器的客户端连接被触发时,可以使用listen方法的回调参数指定回调触发监听事件时调用的函数。回调函数不需要任何参数。如果在上面三种形式的listen方法中没有使用回调参数,可以通过监听TCP服务器对象的监听事件并指定回调函数来指定TCP服务器开始监听时需要执行的处理事件触发时调用server.on('listening',function(){})3.error在TCP服务器上指定要监听的地址和端口时,如果地址和端口已经被占用,错误码为EADDRINUSE会产生(表示用于监听的地址和端口被占用),同样会在TCP服务器上触发错误事件,可以通过设置回调指定错误发生时需要进行的处理错误事件的函数。constnet=require('net');letserver=net.createServer(false,function(ssocket){//这里的socket参数是一个socket对象});server.on('error',function(e){if(e.code==='EADDRINUSE'){console.log('地址和端口被占用,请更正')}});4.address创建TCP服务器后,可以使用TCP服务器的address方法查看服务器监听的地址信息letaddress=server.address();该方法返回一个对象,该对象具有以下属性port:TCP服务器监听的socket端口号address:TCP服务器监听的地址,如127.0.0.1family:标识该地址是否为TCP的字符串server监听的是一个IPv4地址或者一个IPv6地址,比如IPv4使用TCP服务器的getConnections方法查看当前与TCP服务器建立的客户端连接数。同时在控制台输出设置的maxConnections属性值。当当前客户端与服务器的连接数等于该值时,将不再接受新的客户端连接请求。5.关闭每当客户端与服务器建立连接时,第一个命令行窗口会显示当前客户端与TCP服务器的连接数。在新的命令行窗口中与创建的TCP服务器建立连接,TCP服务器将不再接收此连接,第一个命令行窗口中不会有任何变化。可以使用TCP服务器的close方法明确指定服务器拒绝所有新的客户端连接server.close([callback()])使用close方法时,它不会断开所有现有的客户端连接。当这些客户端连接关闭时,TCP服务器会自动关闭,同时触发TCP服务器的关闭事件。close的回调函数是否有参数可以使用。6、Socket端口对象在Node.js中,使用net.Socket表示一个socket端口对象,使用createServer方法的connectionListener参数指定的回调函数(客户端与服务器建立连接时调用)的参数该值是一个自动创建的net.Socket对象(服务器正在监听的端口对象),TCP服务器指定的连接事件回调函数的参数值也是一个自动创建的net.Socket对象(代表端口TCP服务器监听的对象)类似于TCP服务器独有的address方法,可以使用socket端口对象的address方法获取socket端口对象相关的地址信息letaddress=socket.address();该方法返回一个Object,它有如下属性port:TCP服务器监听的socket端口号address:TCP服务器监听的地址,如127.0.0.1family:一个字符串,标识该地址是否为TCPserver监听的是IPv4地址或者IPv6地址,比如可以使用IPv4socket端口对象来读取客户端发送的流数据,每次接收到客户端发送的流数据都会触发data事件,而data事件可以通过监听事件并指定一个回调函数来指定,当server监听的socket端口对象接收到client发送的数据时需要进行的处理。socket.on('data',function(数据){});在这个回调函数中,使用一个参数,参数值是一个Buffer对象(当没有通过socket端口对象的setEncoding方法指定编码时)或者一个字符串对象(当通过socket端口对象的setEncoding方法指定编码方式后)socket端口对象)获取到的数据是一个buffer,里面存放的是服务Object接收到的数据,如果我们监听data事件后使用encoding格式,读取到的数据会在控制台以字符串的形式输出。6.1方法一:constnet=require('net');letserver=net.createServer(false,function(socket){socket.setEncoding('utf8');socket.on('data',function(data){console.log(data);});});6.2方法二:constnet=require('net');letserver=net.createServer(false,function(socket){socket.on('data',function(data){console.log(data.toString());});});7、pipe可以通过socket对象socket.pipe(destination,[options])的pipe方法将client发送的流数据写入到其他目标对象中的文件中;destination参数是必需的输入参数,options参数是可选参数。目标参数的值必须是一个可用于写入流数据的对象。options参数的值是一个Object,你可以在对象中使用一个Booleanend属性。如果该属性值为真,则写入操作将在读取完所有数据后立即结束。如果该属性值为false,目标对象可以继续写入新数据,该属性默认值为true;constnet=require('net');letfile=require('fs').createWriteStream('./message.txt');letserver=net.createServer();server.on('connection',function(socket){socket.pipe(file,{end:false});socket.on('end',function(){file.end('再见');});});server.listen(9999,'localhost');使用unpipe方法取消对目标对象的写操作socket.unpipe([destination]);8.pause可以使用socket端口对象的pause方法来暂停数据事件,此时服务端会将各个客户端发送的数据暂时存放在一个单独的buffer.socket.pause();使用pause方法暂停数据事件的触发后,可以使用socket端口对象的resume方法恢复数据事件的触发。这个时候会读取客户端的缓存数据。套接字.resume();9.timeout是通过监听socket端口对象的timeout事件,指定事件回调函数的方法,当客户端连接超时需要做什么原因constnet=require('net');letserver=net.createServer();server.on('connection',function(socket){socket.setTimeout(10*1000);socket.pause();socket.on('timeout',function(){socket.resume();socket.pipe(file);});socket.on('data',function(data){socket.pause();});});10。一个基本的TCP服务器constnet=require('net');letserver=net.createServer(function(socket){console.log(socket);letaddress=socket.address();console.log('地址信息ofthesocketportobjectis%j',address);//socketport对象的地址信息为{"address":"127.0.0.1","family":"IPv4","port":2596}socket.setEncoding('utf8');socket.on('data',function(data){console.log(data);console.log('接收字节数据长度',socket.bytesRead);/***GET/HTTP/1.1*User-Agent:curl/7.29.0*Host:localhost:2596*Accept://属性值为“asteriskslashasterisk”,因为会和注释冲突,所以不写***接收字节数据长度78**/});//客户端发送的流数据可以通过socket对象的pipe方法写入文件等其他目标对象。套接字管道(文件);socket.on('end',function(){console.log('client客户端连接已关闭');//当客户端连接关闭时,输出“客户端连接已关闭”})});server.getConnections(function(err,count){console.log('当前存在'+count+'客户端连接数');server.maxConnections=2;//设置最大连接数为2console.log('客户端和客户端之间的连接数服务器已经建立');});server.close(function(){console.log('TCPserverisclosed');});server.on('error',function(e){if(e.code==='EADDRINUSE'){console.log('地址和端口被占用,请修复')}});letaddress=server.address();server.listen(2596,'localhost',256,function(){console.log('服务器开始监听');});