整理一下最近的Socket编程

这周例行写一篇。

老师要我做一个WEBp2p聊天工具,我算是报告一下进展吧。

本来的需求是要在web端,也就是浏览器上嵌入一个聊天的工具。

 

一般浏览器端的聊天都是由客户端,也就是浏览器定时向服务器端请求数据,,

这样做的好处:1、简单,跟在页面上向服务器读写数据那样。2、相比于“长连接”会节省资源,据说WebQQ是这样做的。

坏处:1、不够实时,这是显而易见的。

 

另外一种做法是刚才说的长连接,建立COMET的连接框架,实行不断线的连接。

这样做好处:实时。GMail里面的GTalk是这样做的。

坏处:1、超级消耗资源,有100个人连接,服务器就必须保持着100个人的连接。2、难做。

 

还有一种是用Flash做,最新的Flex语言支持SOCKET的客户端,也就是允许客户端主动连接服务器,但是它还不支持Socket的服务端,所以它不能做为p2p的方式进行连接。这样和第一种的方案并没有太多区别。

 

最后一种也就是最没谱的一种,也是没什么把握的一种,也就是我在做的一种,还没做出来的一种。

做成WINFORM形式,当做插件嵌入浏览器,用C/S伪装成B/S。

原谅我吧,这种做法很贱。

 

现在就讲下我是怎么做的。

由于我很菜,是临时才去学的socket,很多东西并不是很熟,有错的地方请指正哈。

其中,代码还参照了很多别人的代码才弄出来的。

 

先简要介绍一下socket,socket的内部协议我也不了解。

我讲得恶心点,就是2部机之间连接2个接口的那根网线。

比如A的IP是192.1.1.1,B的IP是192.1.1.2

A从自己机上的9001端口,连接到B的9002端口,那么Socket就是[192.1.1.1:9001<->192.1.1.2:9002]。

如果这个连接是由A发起的,那么A就是客户端,B就是服务器。

B先打开自己的9002端口,然后A从自己的9001端口引出一条网线,接到B的9002端口。

 

所以AB建立连接的代码可以这样写

B端:

IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, nPort);//ipAddress是本机IP,nPort是本机需要打开(监听)的端口,这个是9002.
Socket Bsocket = new Socket(addressFamily, socketType, protocolType);
Bsocket.Bind(ipLocalEndPoint);//绑定
Bsocket.Listen(10);//最多允许10个连接


这样B端(服务器端)就准备好了。

 

再讲下A端的代码,A端是要从自己发起连接。

A端:

IPEndPoint ipPoint = new IPEndPoint(ipAddress, nPort);//这里的ipAddress是服务器端的IP,也就是B端的IP,nPort也是B端的开放的端口
Socket ASocket = new Socket(addressFamily, socketType, protocolType);
ASocket.Connect(ipPoint);

 

 

这样A端与B端的连接算是建立好了。

那么接下来2端的通信应该是这样:A端容易处理,把需要发送过去的字符转成Byte型的,直接调用ASocket.send(bytedata);

那B端呢,BSocket.send(bytedata)吗?不对,因为BSocket是一个监听的对象,不是一个与A进行连接的对象,而与A连接的对象在哪里呢?

在这:

Socket ClientSocket = BSocket.Accept();//把B监听到的连接交给ClientSocket,这里就是A的了。
ClientSocket.send(bytedata);//这样就OK。

 

 

我们似乎漏了一个环节,有发送,但是没有接受。

对了。接受数据很简单。

Clientket.receive(data); //服务器端得到客户端连接后的写法
BSocket.receive(data); //客户端的写法。

 

 

整段代码整理后应该如下:

B端(服务器端)

Socket serverSocket = new Socket(addressFamily, socketType, protocolType);//这三个参数先忽略。
IPEndPoint localEP = new IPEndPoint("192.168.1.2",1234);
serverSocket.Bind(localEP);
severSocket.Listen();//开始监听

Socket clientSocket = serverSocket.Accept();//程序执行到这里会停下来,直到有连接接入。
byte[] receivedata = new byte[1000];
string message = " ";
while(true)
{
    int i = clientSocket.receive(recievedata);              //通过死循环不断读取数据,i为收到的字节数
    if(i = 0) break;                 //收不到了就跳出
    message += Encoding.Default.GetString(receivedata);         
}

 

A端:

Socket ASocket  = new Socket(addressFamily, socketType, protocolType);//这三个参数先忽略。
IPEndPoint IPEP = new IPEndPoint("192.168.1.1",1234);
ASocket .Connect(IPEP);
byte[] postdata = new byte[1024];
postdata[0]= 1;
ASocket.send(postdata);//发送数据,一般发送数据会作为事件调用使用
byte[] receivedata = new byte[1000];
string message = " ";
while(true)
{
    int i = ASocket.receive(recievedata);              //通过死循环不断读取数据,i为收到的字节数
    if(i = 0) break;                 //收不到了就跳出
    message += Encoding.Default.GetString(receivedata);         
}

 

 

 

 

这是基本的代码,也是没有任何使用价值的代码,首先没有检查连接失败,没有做出多个用户连接的处理,没有对发送的信息进行处理等等等问题。

所以,要真正解决这些问题,要涉及到多线程(多用户,和窗体的不卡死)、缓存(这个可有可无,用于记录已经连接的用户)、事件委托(发送数据接受数据的处理)、异步Socket(提高性能)等等知识。

而这里只是把socket的一些基本函数介绍一下而已。

而且把socket比喻成网线并不合适。总之,大家看着办吧。

 

我做了个局域网的多人聊天工具,源码在你们的师弟钜洪手里,大家想看代码找他,顺便互相认识下。

这个工具就包涵了刚才说的多线程那些东西,可以看看。

 

最后还要说一下,web开发现在越来越强,可是桌面程序还是有它一席之地的,想P2P,js是做不到的。

当然,以后就难说了。

posted on 2010-10-25 23:45  gdutlab624  阅读(400)  评论(0编辑  收藏  举报

导航