求能用的 WebSocket 例子

hmis168 2011-11-29 02:15:37
以下 点链接后 就出现 close connection 不知是什么问题请高手看下
html
-----------------

<html>

<head>

<meta charset="utf-8">

</head>

<script type="text/javascript">

var socket ;

function main(){

try{

socket = new WebSocket("ws://localhost:1806");

socket.onopen = function(){

alert("open Connection !");

socket.send("����");

};

socket.onmessage = function(msg){ alert("receive:" + msg.data);};

socket.onerror = function(msg){alert("error:" + msg);};

socket.onclose = function(msg){alert("close connection"+msg);};

}catch(e){

alert("������ERROR��"+e);

}

}

//window.onload = main;

</script>

<input type="button" value="connect" onclick="main();">

<input type="button" value="send" onclick="socket.send('123');">

<body>

</body>

</html>
---------------------------
package df;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;



/**
*
* @功能 WebServerSocket DEMO
* @作者 蛋蛋
*/
public class WebServerSocket
{
private static final String TAG = "\r\n";
public WebServerSocket(ServerSocket serverSocket)
{
this.serverSocket = serverSocket;
}
ServerSocket serverSocket = null;
/**
* 接收并握手,如果失败,则返回NULL,视为无效的WebSocket,
* @return
* @throws IOException
*/
public void close()
{
try
{
this.serverSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public Socket accept() throws IOException
{
Socket socket = serverSocket.accept();
return startHandshake(socket) ? socket : null;
}
/**
* 握手
* @param socket
* @return
* @throws IOException
*/
private boolean startHandshake(Socket socket) throws IOException
{
socket.setSoTimeout(10000);
InputStream in = socket.getInputStream();

ByteArrayOutputStream requestStream = new ByteArrayOutputStream(){
// 原方法内容 return Arrays.copyOf(buf, count); 下面需要根据\r\n\r\n内容,进行跳出,避免重复创建对象
@Override
public synchronized byte[] toByteArray()
{
return buf;
}
};

while (Boolean.TRUE)
{
requestStream.write((byte)in.read());
byte[] data = requestStream.toByteArray();
//如果当前数据以 \r\n\r\n结尾,则跳出
if (data[requestStream.size() - 1] == 0x0A && data[requestStream.size() - 2] == 0x0D && data[requestStream.size() - 3] == 0x0A && data[requestStream.size() - 4] == 0x0D)
{
break;
}
}
//报文后跟的8个字节 稍后需要他计算MD5
byte[] coda = new byte[8];
if (in.read(coda) != 8)
{
return false;
}
/*String str= "GET /demo HTTP/1.1 \r\n";
str += "Host: example.com \r\n";
str += "Connection: Upgrade\r\n";
str += "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n";
str += "Sec-WebSocket-Protocol: sample\r\n";
str += "Upgrade: WebSocket\r\n";
str += "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n";
str += "Origin: http://example.com";
String str1 = "^n:ds[4U";
byte[] coda = str1.getBytes();
byte[] header = str.getBytes();/
*/
byte[] header = Arrays.copyOf(requestStream.toByteArray(), requestStream.size());
System.out.println("============================请求报文============================");
System.out.println(new String(header));
System.out.println("结尾的8个字节:" +BinaryUtil.formatBytes(coda));
System.out.println("=======================R=====分隔线=============================");
//解析请求报文
Map<String, String> headerMap = parseRequestHeader(header);


//响应请求消息
System.out.println("============================响应消息=============================");
ResponseFrame frame = buildResponseMsg(headerMap,coda);

//拼装的 报文头
System.out.println(frame.getHeader());
System.out.println("MD5(String)===" + new String(frame.getMd5()));
System.out.println("MD5(bytes)===" + BinaryUtil.formatBytes(frame.getMd5()));

//响应握手
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(frame.getHeader().getBytes());
baos.write(frame.getMd5());
socket.getOutputStream().write(baos.toByteArray());
socket.setSoTimeout(0);
return true;
}

/**
* 构建响应消息报文实体.
* @param header 请求消息的报文键值对
* @param coda 请求消息的最后8个字节
* @return frame
* @throws IOException
*/
public static ResponseFrame buildResponseMsg(Map<String,String> header, byte[] coda) throws IOException
{
ResponseFrame frame = new ResponseFrame();
/*
* MD5 部分
* 将 Sec-WebSocket-Key1 和 Sec-WebSocket-Key2
* 以及 请求报文后面的正文的8个字节 转成byte[]
* 再进行MD5签名
*/
ByteArrayOutputStream md5Bytes = new ByteArrayOutputStream();
//协议是 Sec-WebSocket-Key1 和 Sec-WebSocket-Key2 . 我想可能会扩展,就循环了 ^_^!
for (int i = 1;;i++)
{
String key = header.get("Sec-WebSocket-Key" + i);
if(key == null){break;}
md5Bytes.write(MD5(key));
}
md5Bytes.write(coda);
byte[] md5 = md5Bytes.toByteArray();
try
{
//MD5 签名
md5 = MessageDigest.getInstance("MD5").digest(md5);
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
frame.setMd5(md5);

/*
* web socket 响应消息头 部分 ,类似HTTP协议,
*
*/
StringBuilder wsHead = new StringBuilder();
wsHead.append("HTTP/1.1 101 Web Socket Protocol Handshake").append(TAG)
.append("Upgrade: ").append("WebSocket").append(TAG)
.append("Connection: ").append("Upgrade").append(TAG)
.append("Sec-WebSocket-Origin: ").append(header.get("Origin")).append(TAG)
.append("Sec-WebSocket-Location: ").append("ws://localhost/").append(TAG)
//.append("Server: ").append("Kaazing Gateway").append(TAG)
//.append("Date: ").append(new Date()).append(TAG)
//.append("Access-Control-Allow-Origin: ").append(header.get("Origin")).append(TAG)
//.append("Access-Control-Allow-Credentials: ").append("true").append(TAG)
.append(TAG);
frame.setHeader(wsHead.toString());
return frame;
}

/**
* 解析请求消息报文
* @param header Websocket协议的消息头. 最后
* @return map
* @throws IOException
*/
public static Map<String, String> parseRequestHeader(byte[] header) throws IOException
{
Map<String, String> map = new HashMap<String, String>();
BufferedReader reader = new BufferedReader(new StringReader(new String(header)));
//走读 第一行. 即 : GET HTTP1.1 ... 他不在解析范围
reader.readLine();
//开始解析键值对: 如 Upgrade: WebSocket 则 Key=Upgrade Value=WebSocket
while (reader.ready())
{
try{
String[] value = reader.readLine().split(": ");
if(value.length != 2)
{
break;
}
map.put(value[0], value[1]);
}catch(Exception e){break;}
}
return map;
}

/**
* 根据WebSocket 协议
* 如:
* Sec-WebSocket-Key1: 1P:(~7 25Xq46t6ed9T2\ $0
* 将值 "1P:(~7 25Xq46t6ed9T2\ $0" 只保留数字在 除以空格数.
* 最后在转成 byte[] (高字节序,高位在前)
* @param key
* @return
*/
public static byte[] MD5(String key)
{
long number = Long.valueOf(key.replaceAll("\\D", ""));
int spaceSum= key.replaceAll("\\S", "").length();
return spaceSum == 0 ? null : BinaryUtil.formatInteage((int)(number / spaceSum));
}




public static void main(String[] args) throws Exception
{
WebServerSocket server = new WebServerSocket(new ServerSocket(1806));
while(true){
Socket socket=null;
try {
//接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接
socket = server.accept();
if(socket != null)
{
System.out.println(socket.isClosed());
System.out.println(socket);
System.out.println("\n====开始接收 & 回发消息====");
new CreateServerThread(socket);
}

} catch (Exception e) {
e.printStackTrace();
}
}


/*if(socket != null)
{
System.out.println(socket);
System.out.println("\n====开始接收 & 回发消息====");
new CreateServerThread(socket);
new Thread(new Runnable(){
@Override
public void run()
{
try
{
InputStream in = socket.getInputStream();
byte[] data = new byte[2048];
int len = -1;

while (-1 != (len = in.read(data)))
{
byte[] bytes = Arrays.copyOf(data, len);
//消息都是以0x00 打头, 0xFF结尾 收发消息 都是这种格式
System.out.println(BinaryUtil.formatBytes(bytes));
//去取 0x00 打头, 以及0xFF结尾
String clientMsg = new String(bytes,1,bytes.length - 2,"UTF-8");
System.out.println("收到WEB 客户端的消息:" + clientMsg);

ByteArrayOutputStream msg = new ByteArrayOutputStream();
msg.write(0x00);//0x00打头
msg.write("服务端给你发消息了!!..".getBytes("UTF-8"));
msg.write((byte)0xFF);//0xFF结尾

socket.getOutputStream().write(msg.toByteArray());
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}).start();
}*/

}
}


...全文
485 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
哩叔 2012-02-24
  • 打赏
  • 举报
回复
协议不同了
hmis168 2011-11-29
  • 打赏
  • 举报
回复
我用的是谷歌浏览器传服务器的还是 GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: localhost:1808
Origin: null
Sec-WebSocket-Key1: 9%C36tH32'U057q2>HL +
Sec-WebSocket-Key2: 3\8Vp W0600 s2916
chm2920 2011-11-29
  • 打赏
  • 举报
回复
实现Draft-17的WebSocket之体会篇
http://blog.csdn.net/les5332295/article/details/7014799
chm2920 2011-11-29
  • 打赏
  • 举报
回复
不同浏览器支持的 WebSocket 协议不同
到目前新的协议:
http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17

81,092

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧