一个简单的TCP聊天程序

nodejs中创建net服务器

引入nodejs自带的net模块 然后创建一个net服务
其中的conn保存着每个链接,就像你的身份证一般,那个conn就是身份证.在众多的人群(链接)中我总是可以通过conn(身份证)找到你的身影.

1
2
var net=require("net")
var server=net.createServer(function(conn){})

nodejs中的net事件

总所周知nodejs是事件驱动的,So.每个conn都提供了一些事件, 失去链接的事件,链接发送数据的事件.
客户端链接进来了,服务端亦然可以对客户端发送消息表示你已经加入进来了.
客户端发送消息用的是”流”.

引用 nodejs权威指南中的一段话(摘选)
在使用write方法写入数据时,系统首先将该部分数据读到内存,再把数据写入文件
引用 nodejsAPI
socket.write(data, [encoding], [callback])
在套接字上发送数据。第二参数指明了使用字符串时的编码方式-默认为UTF8编码。
如果所有数据被成功刷新到内核缓冲区,则返回true。如果所有或部分数据在用户内存里还处于队列中,则返回false。当缓冲区再次被释放时,’drain’事件会被分发。
当数据最终被完整写入时,可选的callback参数会被执行 - 但不一定是马上执行。

close与end事件
当底层套接字关闭时,nodejs会触发close事件 nodejs中有两个和连接终止相关的事件:end与close.前者是客户端关闭TCP连接时触发,比如你关闭客户端,如Telnet协议的
客户端,telnet会发送一个名为FIN的包给服务器,意味者结束连接.
当连接发生错误时(触发error事件),end事件不会被触发.因为服务端未收到FIN包.这两种情况下 close事件都会被触发.
设置字符编码
conn.setEncoding(“utf8”) //仅仅对于客户端发送的数据有效

1
2
3
4
5
6
7
8
9
10
11
var net=require("net")
conn.setEncoding("utf8")
var server=net.createServer(function(conn){
conn.write("欢迎来到TCP")
conn.on("data",function(data){
console.log(data)//未设置编码是buffer 设置编码则为相应的字符集
})
conn.on("close",function(){
console.log("客户端断开连接")
})
})

开始做一个TCP聊天程序

为了方便解释和说明.我决定把解释都放程序代码块中,涉及到重要的API和知识点再放外面说明
整体思路为
监听用户输入–根据输入判别是否为聊天消息—群发给每个用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var net=require("net")
//创建net服务器
var count=0;
var users={};
var server=net.createServer(function(conn){
var nickname;
//设置获取客户端输入编码
conn.setEncoding("utf8")
count++
conn.write("welcome now conn:"+count+" please input your name and press enter:\r\n")
console.log("当前连接数为:"+count)
//监听退出事件
conn.on("close",function(){
count--
//删除相应的conn
delete users[nickname]
console.log("退出一位链接 当前链接数为"+count)
})
//监听用户输入事件
conn.on("data",function(data){
data=data.replace("\r\n","")
/*
* 这里相当于做路由,因为我们只能监听用户的输入
* 根据用户第一次输入来判断是否输入了姓名,以及用户后续的输入判别为聊天消息
*
* */

//如果还不存在注册姓名
if(!nickname){
//用户输入了触发了data时间 然后再根据data检测.
//检测用户名是否重复
if(users[data]){
conn.write("\r\n nickname already in use try agin: ")
return false;
}else{
//注册用户名
nickname=data
//存储每一个用户链接
//conn相当于身份证 这里就可以通过key value来索引到conn看
users[nickname]=conn
for(var i in users){
users[i].write("\r\n"+nickname+"joined the room\r\n")
}
}
//用户输入了姓名后的消息都视为聊天记录
}else{
//聊天消息
//把消息发送给每个用户
for(var i in users){
//除了发送者本人
if(i!=nickname){
users[i].write(nickname+": "+data+"\r\n")
}
}
}

})
})
server.listen(4120,function(){
console.log("监听4120端口")
})