socket聊天
来源:互联网 发布:沃尔沃xc60拆车坊数据 编辑:程序博客网 时间:2024/04/29 00:26
服务端: 客户端登录: 客户端主界面:
所谓的即时的通信程序,也就是利用TCP和UDP的传输协议,进行信息、文件的传输。那什么是TCP,什么是UDP呢?
TCP是Transmission Control Protocol(传输控制协议)的简称,是TCP/IP体系中面向连接的运输层协议,在网络中提供全双工的和可靠的服务。TCP协议的主要特点是:基于连接的协议,数据传输比较稳定,且可以保证数据按顺序的准时达。
UDP 是User Datagram Protocol(用户数据报协议)的简称,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。UDP协议的主要特点是:基于无连接协议,数据传送迅速,反应快,同时缺点也很明显,就是数据传输不稳定,不能保证数据到达的顺序,可能会有数据的缺失。
我们所熟悉的QQ就是一种基于TCP和UDP两种协议结合的一种即时通信程序,在我们进行会话、聊天的时候,采用UDP协议,通过服务器中转方式。大家都知道,UDP 协议是不可靠协议,它只管发送,不管对方是否收到的,但它的传输很高效。但是,作为聊天软件,怎么可以采用这样的不可靠方式来传输消息呢?于是,腾讯采用了上层协议来保证可靠传输:如果客户端使用UDP协议发出消息后,服务器收到该包,需要使用UDP协议发回一个应答包。如此来保证消息可以无遗漏传输。之所以会发生在客户端明明看到“消息发送失败”但对方又收到了这个消息的情况,就是因为客户端发出的消息服务器已经收到并转发成功,但客户端由于网络原因没有收到服务器的应答包引起的。在我们进行文件传输的时候使用的是基于TCP的数据传输协议,因为要保证传输数据的顺序到达,同时还要保证不能有数据的丢失。
在我们的.NET平台下如果想要实现即时的通信就需要借助于Socket网络编程,Socket(网络套接字)是网络通信的基本构件,它是可以被命名和寻址的通信端口,使用中,每个Socket都有对应的类型和一个与之相关的进程。在开始介绍Socket创建即时通信之前我们需要先了解下使用TCP进行即时通信的操作流程:
下边我会结合这个流程图,一步一步跟大家讲通信的具体流程。
1、创建服务端套接字,监听本机的IP和一个特定的端口,把本机作为服务端。(下面的只是一个简单的演示实例)
int port = 11615;//监听端口,最好设置的大一些,避免和一些特定的端口冲突IPAddress ipAdd=IPAddress.Parse(“192.168.245.1”);//监听IP,我们通过Dns.GetByHostName().Arrylist[],动态获得本机的IP,这里仅是示例。TcpListener listener=new TcpListener(ipAdd, port);//创建监听对象
2、监听服务器端口,等待客户端连接请求
listener.Start();
3、创建客户端的套接字,并向远程服务端发送连接请求
TcpClient tcpClient=new TcpClient();int port = 11615;IPAddress ipAdd=IPAddress.Parse(“192.168.245.1”); tcpClient.Connect(ipAdd, port);
4、服务端确认与客户端的连接,并创建与该客户端对应的Socket对象
Socket clientSocket= listener.AcceptSocket();
5、客户端获取与服务器通信的流通道
NetworkStream stream = tcpClient.GetStream();
6、客户端通过流通道与服务器端进行数据传输
6.1、客户端向服务器端发送数
string hello=“Hello World!”;byte [] buffer=Encoding.Default.GetBytes(hello);stream.Write(buffer,0,buffer.Length);
6.2、客户端接收从服务器端发来的数据
byte [] buffer=new byte[1024];int length= stream.Read(buff,0,buff.Length);string msg = Encoding.Default.GetString(buffer,0,length);
7、服务端接受客户端请求
7.1、服务端向客户端发送数据
string hello=“Hello World!”;byte [] buffer=Encoding.Default.GetBytes(hello);stream.Write(buffer,0,buffer.Length);
7.2、服务端接收从客户器端发来的数据
byte [] buffer=new byte[1024];int length= stream.Read(buff,0,buff.Length);string msg = Encoding.Default.GetString(buffer,0,length);
8、服务端断开与客户端的连接
clientSocket.Close();
9、客户端断开与服务端的连接
tcpClient.Close();
10、服务端关闭服务套接字
tcpClient.Close();
大体的通信流程就是这样子,但是到具体的实际应用中还有不同 ,因为我们要涉及到多个客户端之间的交互,而服务端只是相当于一个中间的媒介,接收客户端传递的消息,并将消息转发给另一个客户端,如果有多个客户端,同时进行通信,而这个时候就需要用到多线程进行通信的管理和控制。
具体的流程如下:
首先,我们在需要服务端创建一个TCPLister对象,启用一个线程,专门负责监听客户端的请求。
其次,只要有一个客户端进行请求 ,则TCPLister对象会马上创建一个专门负责通信的Socket与客户端请求的套接字,
同时再启用一个新的线程专门负责与客户端进行通信。
在客户端,我们只需要创建一个TCPClient对象,启用一个新的线程来专门的负责信息的接受即可。
在具体的通过过程中,我们还需要定制一些列的消息通信协议,在消息内部用“|”管道符将其内容进行分割,通过对协议的解析我们可以对不同的消息做不同的处理。在本应用才程序中,具体的通信协议如下:
在服务端接收协议如下:
命令格式
接收到客户端发送的通信流的字节数组中的首字节Msg[0]
说明
1、如果Msg[0]则说明发送的是文件,则遍历在线用户列表,像用户在线用户逐一发送该字节数组
2、如果Msg[0]!=0,则说明发送过来的信息字符串,则直接进行Encoding将字节数组转换为字符串,并对字符串进行如下的分析,根据不同的分析结果执行不同的命令。
ON|发送者的用户名|
1、该命令在客户端与服务器端建立连接后由客户端自动发送
2、服务器端收到该命令后,将“用户名”添加到在线用户列表并向所有在线用户发送消息“***上线啦!"
Off|发送者的用户名|
1、该命令是在用户上线、或者离开时执行的,用于向客户端发送在线人员名单,客户端接受到该信息后就会对在线列表进行更新。
MSG|接收者姓名|发送者姓名|发送内容|
MSGALL|发送者的用户名|发送内容|
1、该命令是用户点击发送消息按钮时,发送的信息,前提是用户必须选定要发送的对象
2、服务端收到该消息后,对消息进行解析,从中取得接受者用户名,并从在线列表中取得相应的通讯Socket,将“发送者用户名说“发送内容“这样格式的消息发送回客户端
3、如果是MSGALL,则为群发消息,服务器端收到该命令后,将遍历在线用户列表的用户,并逐一向在线用户发送”发送者的用户名说‘发送内容’”这样的信息发送给所有的在线用户
在客户端接收协议如下:
命令格式
说明
接受服务端发送的通信流字节数组中的首字节Msg[0]
如果Msg[0]==0则说明服务端发送的是文件,直接新建文件流从接收到的字节数组中的第二个字节开始读取,读取长度为字节数组长度减一个字节,并在本地保存文件。
如果Msg[0]!=0则说明服务端发送的是消息字符串,然后再根据下面的命令格式进行解析,进而做出不同的操作
OnLine|刚登录的用户名|
客户端收到该命令后,在聊天串口中看到“****”上线了的通知!
Off|用户1、用户2、用户3、|
该命令是在服务器端收到客户端发来的Off和On命令,回发给客户端的命令,然后客户端解析命令,更新在线人员列表。
以上这些就是该即时通信程序的通信格式,在下一节中,我会带领大家一步一步的构建该即时通信程序的服务端,在构建的过程中会逐步向大家演示TCPLister的应用,以及相关的涉及的多线程的知识。
好了,这一节就到这里了,希望能给大家带来些许帮助,同时也希望大家多多指点。
- Socket聊天
- socket聊天
- Socket聊天
- 聊天 一对一 Socket
- flash socket 聊天(一)
- flash socket 聊天(二)
- socket编程网络聊天
- SOCKET聊天客户端
- java socket 聊天
- linux socket聊天程序
- java socket聊天
- Socket聊天程序(Server)
- Socket聊天程序(Client)
- android socket 聊天实现
- 【JAVA】socket 聊天系统
- c++编写socket聊天
- socket 简单聊天示例
- nodejs+socket聊天系统
- GraphLab:新的面向机器学习的并行框架
- Apache数组创建、使用的过程分析
- mysql主从复制配置
- spring security3.25 配置异常集合
- getAttribute和getParameter区别
- socket聊天
- javaMail
- zz:重装windows后覆盖掉ubuntu的引导的恢复,以及更改默认引导顺序
- c#如何将winform窗体封装成可以引用的dll文件
- 高效e人--您最好的时间管理专家
- Java 字符串分割
- linux,/etc/passwd,/etc/shadow详解
- Linux下重启php的办法【php版本5.3.16】
- Android 三种sendBroadCast的方式对比