标准websocket即时通讯通讯怎么弄

二次元同好交流新大陆
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
追求所追求的
放弃所放弃的
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(7761)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'c语言socket通信',
blogAbstract:'网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。
什么是Socket
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的',
blogTag:'',
blogUrl:'blog/static/9',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:9,
permalink:'blog/static/9',
commentCount:0,
mainCommentCount:0,
recommendCount:2,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'追求所追求的
放弃所放弃的',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}本节引言:
上节中我们给大家接触了Socket的一些基本概念以及使用方法,然后写了一个小猪简易聊天室的
Demo,相信大家对Socket有了初步的掌握,本节我们来学习下使用Socket来实现大文件的断点续传!
这里讲解的是别人写好的一个Socket上传大文件的例子,不要求我们自己可以写出来,需要的时候会用
1.运行效果图:
1.先把我们编写好的Socket服务端运行起来:
2.将一个音频文件放到SD卡根目录下:
3.运行我们的客户端:
4.上传成功后可以看到我们的服务端的项目下生成一个file的文件夹,我们可以在这里找到上传的文件:
.log那个是我们的日志文件
2.实现流程图:
3.代码示例:
先编写一个服务端和客户端都会用到的流解析类:
StreamTool.java:
public class StreamTool {
public static void save(File file, byte[] data) throws Exception {
FileOutputStream outStream = new FileOutputStream(file);
outStream.write(data);
outStream.close();
public static String readLine(PushbackInputStream in) throws IOException {
char buf[] = new char[128];
int room = buf.
int offset = 0;
while (true) {
switch (c = in.read()) {
case '\n':
case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) in.unread(c2);
if (--room & 0) {
char[] lineBuffer =
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
buf[offset++] = (char)
if ((c == -1) && (offset == 0))
return String.copyValueOf(buf, 0, offset);
* @param inStream
* @return 字节数组
* @throws Exception
public static byte[] readStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while( (len=inStream.read(buffer)) != -1){
outSteam.write(buffer, 0, len);
outSteam.close();
inStream.close();
return outSteam.toByteArray();
1)服务端的实现:
socket管理与多线程管理类:
FileServer.java:
public class FileServer {
private ExecutorService executorS//线程池
//监听端口
private boolean quit =//退出
private ServerS
private Map&Long, FileLog& datas = new HashMap&Long, FileLog&();//存放断点数据
public FileServer(int port){
this.port =
//创建线程池,池中具有(cpu个数*50)条线程
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 50);
public void quit(){
this.quit =
server.close();
} catch (IOException e) {
* 启动服务
* @throws Exception
public void start() throws Exception{
server = new ServerSocket(port);
while(!quit){
Socket socket = server.accept();
//为支持多用户并发访问,采用线程池管理每一个用户的连接请求
executorService.execute(new SocketTask(socket));
} catch (Exception e) {
e.printStackTrace();
private final class SocketTask implements Runnable{
private Socket socket =
public SocketTask(Socket socket) {
this.socket =
public void run() {
System.out.println("accepted connection "+ socket.getInetAddress()+ ":"+ socket.getPort());
PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());
//得到客户端发来的第一行协议数据:Content-Length=;filename=xxx.3sourceid=
//如果用户初次上传文件,sourceid的值为空。
String head = StreamTool.readLine(inStream);
System.out.println(head);
if(head!=null){
//下面从协议数据中提取各项参数值
String[] items = head.split(";");
String filelength = items[0].substring(items[0].indexOf("=")+1);
String filename = items[1].substring(items[1].indexOf("=")+1);
String sourceid = items[2].substring(items[2].indexOf("=")+1);
long id = System.currentTimeMillis();//生产资源id,如果需要唯一性,可以采用UUID
FileLog log =
if(sourceid!=null && !"".equals(sourceid)){
id = Long.valueOf(sourceid);
log = find(id);//查找上传的文件是否存在上传记录
File file =
int position = 0;
if(log==null){//如果不存在上传记录,为文件添加跟踪记录
String path = new SimpleDateFormat("yyyy/MM/dd/HH/mm").format(new Date());
File dir = new File("file/"+ path);
if(!dir.exists()) dir.mkdirs();
file = new File(dir, filename);
if(file.exists()){//如果上传的文件发生重名,然后进行改名
filename = filename.substring(0, filename.indexOf(".")-1)+ dir.listFiles().length+ filename.substring(filename.indexOf("."));
file = new File(dir, filename);
save(id, file);
}else{// 如果存在上传记录,读取已经上传的数据长度
file = new File(log.getPath());//从上传记录中得到文件的路径
if(file.exists()){
File logFile = new File(file.getParentFile(), file.getName()+".log");
if(logFile.exists()){
Properties properties = new Properties();
properties.load(new FileInputStream(logFile));
position = Integer.valueOf(properties.getProperty("length"));//读取已经上传的数据长度
OutputStream outStream = socket.getOutputStream();
String response = "sourceid="+ id+ ";position="+ position+ "\r\n";
//服务器收到客户端的请求信息后,给客户端返回响应信息:sourceid=4;position=0
//sourceid由服务器端生成,唯一标识上传的文件,position指示客户端从文件的什么位置开始上传
outStream.write(response.getBytes());
RandomAccessFile fileOutStream = new RandomAccessFile(file, "rwd");
if(position==0) fileOutStream.setLength(Integer.valueOf(filelength));//设置文件长度
fileOutStream.seek(position);//指定从文件的特定位置开始写入数据
byte[] buffer = new byte[1024];
int len = -1;
int length =
while( (len=inStream.read(buffer)) != -1){//从输入流中读取数据写入到文件中
fileOutStream.write(buffer, 0, len);
Properties properties = new Properties();
properties.put("length", String.valueOf(length));
FileOutputStream logFile = new FileOutputStream(new File(file.getParentFile(), file.getName()+".log"));
properties.store(logFile, null);//实时记录已经接收的文件长度
logFile.close();
if(length==fileOutStream.length()) delete(id);
fileOutStream.close();
inStream.close();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
if(socket!=null && !socket.isClosed()) socket.close();
} catch (IOException e) {}
public FileLog find(Long sourceid){
return datas.get(sourceid);
//保存上传记录
public void save(Long id, File saveFile){
//日后可以改成通过数据库存放
datas.put(id, new FileLog(id, saveFile.getAbsolutePath()));
//当文件上传完毕,删除记录
public void delete(long sourceid){
if(datas.containsKey(sourceid)) datas.remove(sourceid);
private class FileLog{
public Long getId() {
public void setId(Long id) {
public String getPath() {
public void setPath(String path) {
this.path =
public FileLog(Long id, String path) {
this.path =
服务端界面类:ServerWindow.java:
public class ServerWindow extends Frame {
private FileServer s = new FileServer(12345);
public ServerWindow(String title) {
super(title);
label = new Label();
add(label, BorderLayout.PAGE_START);
label.setText("服务器已经启动");
this.addWindowListener(new WindowListener() {
public void windowOpened(WindowEvent e) {
new Thread(new Runnable() {
public void run() {
s.start();
} catch (Exception e) {
// e.printStackTrace();
}).start();
public void windowIconified(WindowEvent e) {
public void windowDeiconified(WindowEvent e) {
public void windowDeactivated(WindowEvent e) {
public void windowClosing(WindowEvent e) {
System.exit(0);
public void windowClosed(WindowEvent e) {
public void windowActivated(WindowEvent e) {
* @param args
public static void main(String[] args) throws IOException {
InetAddress address = InetAddress.getLocalHost();
ServerWindow window = new ServerWindow("文件上传服务端:" + address.getHostAddress());
window.setSize(400, 300);
window.setVisible(true);
2)客户端(Android端)
首先是布局文件:activity_main.xml:
&?xml version="1.0" encoding="utf-8"?&
&LinearLayout xmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="5dp"&
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="文件名"
android:textSize="18sp" /&
android:id="@+id/edit_fname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Nikki Jamal - Priceless.mp3" /&
android:id="@+id/btn_upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上传" /&
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止" /&
&ProgressBar
android:id="@+id/pgbar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="40px" /&
android:id="@+id/txt_result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" /&
&/LinearLayout&
因为断点续传,我们需要保存上传的进度,我们需要用到数据库,这里我们定义一个数据库
管理类:DBOpenHelper.java::
* Created by Jay on
public class DBOpenHelper extends SQLiteOpenHelper {
public DBOpenHelper(Context context) {
super(context, "jay.db", null, 1);
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS uploadlog (_id integer primary key autoincrement, path varchar(20), sourceid varchar(20))");
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
然后是数据库操作类:UploadHelper.java:
* Created by Jay on
public class UploadHelper {
private DBOpenHelper dbOpenH
public UploadHelper(Context context) {
dbOpenHelper = new DBOpenHelper(context);
public String getBindId(File file) {
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select sourceid from uploadlog where path=?", new String[]{file.getAbsolutePath()});
if (cursor.moveToFirst()) {
return cursor.getString(0);
public void save(String sourceid, File file) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("insert into uploadlog(path,sourceid) values(?,?)",
new Object[]{file.getAbsolutePath(), sourceid});
public void delete(File file) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("delete from uploadlog where path=?", new Object[]{file.getAbsolutePath()});
对了,别忘了客户端也要贴上那个流解析类哦,最后就是我们的MainActivity.java了:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText edit_
private Button btn_
private Button btn_
private ProgressB
private TextView txt_
private UploadHelper upH
private boolean flag =
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
pgbar.setProgress(msg.getData().getInt("length"));
float num = (float) pgbar.getProgress() / (float) pgbar.getMax();
int result = (int) (num * 100);
txt_result.setText(result + "%");
if (pgbar.getProgress() == pgbar.getMax()) {
Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_SHORT).show();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
upHelper = new UploadHelper(this);
private void bindViews() {
edit_fname = (EditText) findViewById(R.id.edit_fname);
btn_upload = (Button) findViewById(R.id.btn_upload);
btn_stop = (Button) findViewById(R.id.btn_stop);
pgbar = (ProgressBar) findViewById(R.id.pgbar);
txt_result = (TextView) findViewById(R.id.txt_result);
btn_upload.setOnClickListener(this);
btn_stop.setOnClickListener(this);
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_upload:
String filename = edit_fname.getText().toString();
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File file = new File(Environment.getExternalStorageDirectory(), filename);
if (file.exists()) {
pgbar.setMax((int) file.length());
uploadFile(file);
Toast.makeText(MainActivity.this, "文件并不存在~", Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "SD卡不存在或者不可用", Toast.LENGTH_SHORT).show();
case R.id.btn_stop:
private void uploadFile(final File file) {
new Thread(new Runnable() {
public void run() {
String sourceid = upHelper.getBindId(file);
Socket socket = new Socket("172.16.2.54", 12345);
OutputStream outStream = socket.getOutputStream();
String head = "Content-Length=" + file.length() + ";filename=" + file.getName()
+ ";sourceid=" + (sourceid != null ? sourceid : "") + "\r\n";
outStream.write(head.getBytes());
PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());
String response = StreamTool.readLine(inStream);
String[] items = response.split(";");
String responseSourceid = items[0].substring(items[0].indexOf("=") + 1);
String position = items[1].substring(items[1].indexOf("=") + 1);
if (sourceid == null) {//如果是第一次上传文件,在数据库中不存在该文件所绑定的资源id
upHelper.save(responseSourceid, file);
RandomAccessFile fileOutStream = new RandomAccessFile(file, "r");
fileOutStream.seek(Integer.valueOf(position));
byte[] buffer = new byte[1024];
int len = -1;
int length = Integer.valueOf(position);
while (flag && (len = fileOutStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
length +=//累加已经上传的数据长度
Message msg = new Message();
msg.getData().putInt("length", length);
handler.sendMessage(msg);
if (length == file.length()) upHelper.delete(file);
fileOutStream.close();
outStream.close();
inStream.close();
socket.close();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "上传异常~", Toast.LENGTH_SHORT).show();
}).start();
最后,还有,记得往**AndroidManifest.xml**中写入这些权限哦!
&!-- 在SDCard中创建与删除文件权限 --&
&uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/&
&!-- 往SDCard写入数据权限 --&
&uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&
&!-- 访问internet权限 --&
&uses-permission android:name="android.permission.INTERNET"/&
4.代码下载:
5.本节小结:
本节给大家介绍了基于TCP协议的Socket的另一个实例:使用Socket完成大文件的续传,
相信大家对Socket的了解更进一步,嗯,下一节再写一个例子吧,两个处于同一Wifi
下的手机相互传递数据的实例吧!就说这么多,谢谢~
7.6.3 基于TCP协议的Socket通信(2)一、网络中进程之间如何通信?
&&&&&socket一词的起源:在组网领域的首次使用是在日发布的文献中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:&命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。&计算机历史博物馆补充道:&这比BSD的套接字接口定义早了大约12年。&
3.3、网络字节序与主机字节序
主机字节序:就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:
  a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
  b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
3.4、listen()、connect()函数
SYN表示建立连接,
FIN表示关闭连接,
ACK表示响应,
PSH表示有 DATA数据传输,
RST表示连接重置。
我们知道tcp建立连接要进行&三次握手&,即交换三个分组。大致流程如下:
&&&&&& 只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:
阅读(...) 评论()> WebSocket技术在实时WEB通讯中的应用研究
WebSocket技术在实时WEB通讯中的应用研究
  1.前言
  作为下一代的Web标准,HTML5拥有许多引人注目的新特性,如Canvas、本地存储、多媒体编程接口、WebSocket等,有两大特点:首先,强化Web网页的表现性能。其次,追加本地数据库等Web应用的功能。包括HTML、CSS和JavaScript在内的一套技术组合,减少浏览器对于需要插件的丰富性网络应用服务(plug-inbasedrich internet application,RIA),如Adobe Flash、Microsoft Silverlight与OracleJavaFX的需求,并且提供更多能有效增强网络应用的标准集。而有“Web的TCP”支撑的WebSocket在打破了现有的WEB网络通讯编程模式,WebSocket使得浏览器提供对Socket的支持成为可能,在浏览器和服务器之间提供了一个基于TCP连接的双向通道,使得开发人员可以方便构建实时Web应用。
  2.传统实时WEB的通讯技术
  传统的Web应用的信息交互过程是客户端通过浏览器发出一个请求(Request),服务器端接收和审核完请求后进行处理(Response)并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,但对于那些实时要求比较高的应用来说,当客户端浏览器准备呈现服务器返回的数据信息时,信息有可能已经过时了。保持客户端和服务器端的信息同步是实时Web应用的关键要素。在WebSocket规范出来之前,开发人员想实现实时Web应用,只能采用如轮询(Polling)或Comet技术方案,而Comet则是轮询技术的改进,长轮询机制与流技术。
  轮询:客户端以一定的时间间隔向服务端发出请求,以频繁请求的方式来保持客户端和服务器端的同步。问题在于:当客户端以固定频率向服务器发起请求的时候,服务器端的数据可能并没有更新,造成无谓的网络传输,属于低效的实时方案。
  长轮询:长轮询是对定时轮询的改进和提高,目地是降低无效的网络传输。当服务器端没有数据更新时,连接会保持一段时间周期直到数据或状态改变或者时间过期,通过这种机制来减少无效的客户端和服务器间的交互。当服务端数据变更非常频繁时,就和定时轮询没有本质上性能提高。
  流:通常在客户端的页面使用一个隐藏的窗口向服务端发出一个长连接的请求。服务器端接到这个请求后作出回应并不断更新连接状态以保证客户端和服务器端的连接不过期。
  将服务器端的信息不断推向客户端。但需要针对不同的浏览器设计不同的方案来改进用户体验,同时在并发比较大的情况下,对服务器端的资源是一个极大的考验。
  以上方案只是利用Ajax方式来模拟实时的效果,每次交互都是HTTP的请求和应答的过程,每次都带有一套完整的HTTP头信息,增加了传输的数据量,在实际的应用中,为了模拟真实的实时效果,需要构造两个HTTP连接来模拟客户端和服务器之间的双向通讯,一个连接用来处理客户端到服务器端的数据传输,一个连接用来处理服务器端到客户端的数据传输,增加编程实现的复杂度,同时增加了服务器端的负载,制约了应用系统的扩展性。
  3.HTML 5 WebSocket概念及规范
  WebSocket API是下一代客户端-服务器的异步通信方法。取代了单个的TCP套接字,使用ws或wss协议,在任意的客户端和服务器程序通讯。WebSocket目前由W3C进行标准化,已经受到Firefox 4、Chrome 4、Opera 10.70以及Safari 5等浏览器的支持,在给定的时间范围内的任意时刻,相互推送信息。
  HTML5 Web Sockets从一个Web客户端连接到一个远程端点,需要创建WebSocket实例并为之提供一个URL来表示想要连接到的远程端点。该规范定义了ws://以及wss://模式来分别表示WebSocket和安全WebSocket连接。一个WebSocket连接是在客户端与服务器之间HTTP协议的初始握手阶段将其升级到Web Socket协议来建立的,其底层仍是TCP/IP连接。
  其中:
  WS:表示HTML5 WEB Sockets协议;
  Host:表示服务器的地址;
  Port:表示待链接的端口;
  WebSocket Server:表示Server请求资源地址。
  Web Sockets使用HTTP Upgrade机制升级到Web Socket协议,同时兼容HTTP的握手机制,因此HTTP服务器可以与WebSocket服务器共享默认的HTTP与HTTPS端(80和443)。要建立一个WebSocket连接,客户端和服务器在初次握手的时候从HTTP协议提升到Web Socket协议。客户端浏览器首先要向服务器发起一个HTTP请求,这个请求和通常的HTTP请求不同,包含了一些附加头信息,其中附加头信息“Upgrade:WebSocket”,表明是一个申请协议升级的HTTP请求,服务器端解析附加的头信息,产生应答信息返回给客户端,由此客户端和服务器端的WebSocket建立成功,然后通过链接通道自由传递信息,并且持续到客户端或者服务器端的单方主动关闭连接。连接建立后,WebSocket数据帧以全双工的模式在客户端和服务器之间来回传输。
  典型WebSocket请求与响应例子如下:
  其中Sec-WebSocket-Key1,Sec-WebSocket-Key2和[8-byte security key]这几个头信息是WebSocket服务器用来生成应答信息的来源,服务器基于以下的算法来产生正确的应答信息:
  a)逐个字符读取Sec-WebSocket-Key1头信息中的值,将数值型字符连接到一起放到一个临时字符串里,同时统计所有空格的数量;
  b)将在第1步里生成的数字字符串转换成一个整型数字,然后除以第1步里统计出来的空格数量,将得到的浮点数转换成整数型;
  c)将第2步里生成的整型值转换为符合网络传输的网络字节数组;
  d)对Sec-WebSocket-Key2头信息同样进行第1到第3步的操作,得到另外一个网络字节数组;
  e)将[8-byte security key]和在第3,第4步里生成的网络字节数组合并成一个16字节的数组;
  f)对第5步生成的字节数组使用MD5算法生成一个哈希值,这个哈希值就作为安全密钥返回给客户端,以表明服务器端获取了客户端的请求,同意创建WebSocket连接。
  服务端将生成的网络字节数组和客户端提交的头信息里的[8-byte security key]
  合并成一个1 6 位字节数组并用M D 5 算法加密,然后将生成的安全密钥作为应答信息返回给客户端,由此建立双方的WebSocekt连接通道,实现WebSocket握手信息的处理逻辑。WbSocket服务器由两个核心类构成,一个是WebSocketServer,另外一个是SocketConnection.
  实际的开发过程中,为构建Web应用,首先需要构建WebSocket规范的服务器,服务器端的实现不受平台和开发语言的限制,只需要遵从WebSocket规范即可。
  如果使用的是一个未加密的WebSocket连接(ws://),在透明的代理服务器情况下,浏览器是不知道代理服务器的,所以不会发送HTTP CONNECT方法。如使用的是加密的WebSocket安全连接(wss://),那么在透明代理服务器下,浏览器不知道代理服务器,所以不会发出HTTPCONNECT方法。然而,因为线上信息是加密的,中间透明代理服务器会简单的让加密信息通过,因此就增加了使用加密的WebSocket连接的成功率。
  HTML5 WebSocket目的是取代轮询和Comet技术,使客户端浏览器具备像C/S架构下桌面系统的实时通讯能力。浏览器通过JavaScript向服务器发出建立WebSocket连接的请求,连接建立以后,客户端和服务器端就可以通过TCP连接直接交换数据。因为WebSocket连接本质上就是一个TCP连接,所以在数据传输的稳定性和数据传输量的大小方面,和轮询以及Comet技术比较,具有很大的性能优势。
  4.WebSocket JavaScript接口定义
  针对WebSocket JavaScript客户端接口定义相对比较简单:
  其中 URL属性代表WebSocket服务器的网络地址,协议通常是“ws”,send方法就是发送数据到服务器端,close方法就是关闭连接。除了这些方法,还有一些很重要的事件:
  onOpen,onMessage,onError以及onClose.
  5.WebSocket应用场景
  5.1 初始数据前台展示
  初始数据通过后台的数据推送方法到客户端,客户端可以在回调函数中收到信息,通过HTML5组件来展示这些信息。
  5.2 后台推送信息,前台实时更新
  增加后台推送信息代码,在后台起一个定时器,定时推送产生消息或者清除信息,并将信息推送给所有的客户端。
  5.3 客户端拖拽节点,同步到其他客户端
  增加拖拽同步,监听网内所有信息点,将节点位置信息发送给后台,后台接收到节点位置信息后,更新后台数据,然后将消息转发给其他客户端,实现信息同步操作。
  6.WebSocket应用展望
  WebSocket作为一个正在演变中的Web规范,目前用WebSocket构建应用程序可能存在一些风险。WebSocket规范和API存在变动的可能,尽管目前存在一些局限性,但WebSocket将会成为未来开发实时Web应用的生力军。
免责声明:
&&&&本网转载之文章来源于互联网,转载目的在于传递更多信息,不代表本网赞同其观点和对其真实性负责。如因作品内容、版权问题存在异议的,请在30日内与本网联系。联系方式:2
热门评论Top5
您有何高见
存储器¥3.52
430微控制器¥6.00
接口器件¥45.77
数据转换器¥256.81
美国国际消费类电子产品展览会(CES)是世界最大的消费类电子产品和技术的年度会展,其规模在全美各类年度会展中首屈一指。该展始于1967年,迄今已有45年
日至11月1日,以“信息化推动工业化,电子技术促进产业升级”为主题的第80届中国电子展(CEF)在上海新国际博览中心隆重开幕。
设计与运用
合作与转让
违规与防骗
工艺、材料与封装
标准、政策与法规
扑克牌人物评选
电子产业回顾与展望
版权所有 不得转载}

我要回帖

更多关于 android socket通讯 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信