socket多客户端连接服务器

    关于套接字编程,我们可以使用它来完成网络通信,而关于使用socket来实现多客户端连接服务器,我记录了以下东西。
    一.基本思路
       1.服务器实例化serversocket,并监听本机自定义端口,等待客户端的连接,在这里,当然我们可以为其开一个线程来完成其工作。
(*使用线程?比方说,我们写的是一个web项目,需要如tomcat等服务器启动时就开启socket服务器,我们应该:
1.在web.xml添加监听器
<listener>
<listener-class>com.util.InitServerUtil</listener-class>
</listener>
2.编写监听器,让其实现ServletContextListener接口
public void contextDestroyed(ServletContextEvent sce) {
Server.stopServer();
}
public void contextInitialized(ServletContextEvent sce) {
if (Server.startServer())
System.out.println("\nRun Success!\n");
else
System.out.println("Run failed!");
}
Server.startServer()方法即是开启服务器的代码,而在这里,即是线程意义所在,如果不使用线程,那么                    startServer()方法代码即是
public static void startServer(){
serverSocket = new ServerSocket(22222);
while (true) {
socket = serverSocket.accept();
String Name = "Mac" + ++count;// 服务器给用户暂定硬件名
ClientConnection ccon = new ClientConnection(socket, macName);//为socket分配线程接收服务器消息
Hmap.put(Name, ccon);// 将该客户端连接加入哈希map
}
}

        很明显,该方法里面存在一个while的死循环,那么导致的后果是,该方法一直执行while循环而永不返回,它不返回,那么Server.startServer()代码永远阻塞在这儿,导致于tomcat服务器一直停在这儿,而间接开启失败。而如果我们使用了线程:
public static void startServer(){
listen = new Thread(listenTask);//listenTask-线程执行的任务,用于开启socket服务器,而代码即是上面的while循环内容
listen.start();
}

       那么,startServer()方法仍然返回,它的任务交给线程去执行了,即是异步。这样,tomcat也就启动成功了。
      
      2.客户端实例化socket并设定要连接的服务器地址和端口(IP+port),进行连接。
      3.客户端连接上服务器,服务器执行连接成功后的代码(即accept()方法之后),这时应该将accept()返回的socket对象连同对应的客户端标识信息,保存起来(如使用ConcurrentHashMap来保存)。同时,应该开一个线程用来完成一个任务---①时刻准备接收客户端发送来的消息,也就是说在服务器为每个客户端都开一个线程用来完成接收客户端消息的任务。
(*为何使用ConcurrentHashMap?可查看http://blog.csdn.net/xuefeng0707/article/details/40834595)

        4.对应地,每个客户端也应该开一个线程用来时刻接收服务器发送来的消息。
      5.数据收发:
       客户端使用连接服务器的socket,调用socket的输出流进行写操作向服务器写数据
       客户端的接收服务器消息线程完成服务器数据读操作
       服务器为每个客户端开的线程用来完成客户端向服务器写数据的任务
       服务器将保存的对应客户端的socket取出,调用socket的输出流进行写操作向客户端写数据
     二、数据格式(关于上面的“①时刻准备接收客户端发送来的消息”)
       对于socket,有的人采用字符流进行数据传送,有的人采用字节流进行传输。各自的优劣好坏,我浅谈一下,
       1.字符流传输
       相应代码举例
while (true) {
in = new DataInputStream(socket.getInputStream());
String str;
if ((str = in.readUTF()) != null) {
message= str;
}
}  

       这里将socket的inputstream进一步封装为DataInputStream,进而调用其readUTF()方法。此时,在while死循环中,程序执行到in.readUTF()时,如果客户端发送的数据为空,那么程序会阻塞到该位置,直到socket中有数据为止,而不会继续执行下面的代码了,即不会再一直while循环了,使用这样的方式,有一个好处,那就是因为这个阻塞会导致程序能时刻知道你客户端是否一直和服务器连上的,一旦断开,会引发异常 ,这样,我们就可以通过捕捉异常的方式来时刻知道,客户端是否处于连接状态。                             
       2.字节流传输
       相应代码举例:
while (true) {
in = socket.getInputStream();
buff = new byte[in.available()];
if (in.read(buff) > 0) {
message= new String(buff);
}
}

        此时,在while无限循环的情况下,while循环体中的代码会被无限循环,而每次循环时都进行一次if判断,如果客户端传送的字节数据>0,即将字节数据组合成字符串,即是客户端发送的消息,否则继续循环。这里,如果用户没有传送数据过来,in.read(buff)返回的是0,这样的一直判断会导致cpu将所有的时间片用于这个while循环,即连上一个客户端,cpu就爆满了,当然如果是四核处理器,那么连上四个客户端,同样GG。对于此,可使用线程休眠来解决:
          Thread.sleep(700);
       一般休眠时间在700毫秒及以下即可保证时刻都能接收到客户端的消息。而对应想要时刻知道客户端是否处于连接状态,就只能另辟蹊径,比如使用心跳机制:
public Boolean isRemoteClose(Socket socket) {
try {
socket.sendUrgentData(0);// 发送1个字节的紧急数据,默认情况下,服务器端没有开启紧急数据处理,不影响正常通信
return false;
} catch (SocketException se) {
return true;
} catch (IOException e) {
return true;
}
}
     需要注意的是:对于windows系统,处于安全考虑,对于心跳机制是持有不支持态度的,即对于时刻发生心跳包是会被阻止的,一般发生了17个心跳包左右,就不在允许你再发送了。因此,只能在每次进行通信的时候,进行一次发送数据的试探,这个数据最好是一个没用的数据,如果可以发送成功,表示客户端是连接上的。
           
     相关demo在:http://download.csdn.net/detail/localhost01/9538007

socket多客户端连接服务器相关推荐

  1. 虚拟机客户端怎么连接服务器,虚拟机客户端连接服务器

    虚拟机客户端连接服务器 内容精选 换一换 本章节指导您使用MongoDB客户端和Robo 3T工具,通过公网连接集群实例.通过MongoDB客户端和Robo 3T工具连接实例的方式有普通连接和SSL连 ...

  2. 服务器修改了 金碟软件用不到,金蝶软件金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置...

    金蝶软件金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置 金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示"服务器不是有效的, ...

  3. t3客户端连接服务器就未响应,t3标准版客户端连接服务器方法

    t3标准版客户端连接服务器方法 内容精选 换一换 SSL证书是一种遵守SSL协议的服务器数字证书,可以在客户端和服务器端之间建立加密通道,保证数据在传输过程中不被窃取或篡改.为了提高数据安全性,Gau ...

  4. 重装金蝶专业版后服务器不显示错误,金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置...

    金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置 金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示"服务器不是有效的,请重新设 ...

  5. u8系统怎么连接服务器,怎么U8客户端连接服务器

    怎么U8客户端连接服务器 内容精选 换一换 本章节为您介绍以下内容:准备弹性云服务器作为GDS服务器在使用GDS导入导出数据之前,需要准备一台或多台与GaussDB(DWS) 集群在相同VPC内的Li ...

  6. java socket 编程 客户机服务器_Java Socket编程服务器响应客户端实例代码

    通过输入流来读取客户端信息,相应的时候通过输出流来实现. 服务端类的代码: import java.io.BufferedReader; import java.io.IOException; imp ...

  7. python tcp多个客户端连接服务器

    一.传输层** 该层为两台主机上的应用程序提供端到端的通信.传输层有两个传输协议:TCP(传输控制协议)和 UDP(用户数据报协议).其中,TCP是一个可靠的面向连接的协议,udp是不可靠的或者说无连 ...

  8. python实现socket多客户端连接

    socket实现同网络下不同机器之间互联,常规写法,直接创建后只能有一个客户端连接到服务端,无法实现多客户端连接.在这里使用多线程的方法创建多个监听来实现多客户端连接同一个服务端. server端代码 ...

  9. Linux C TCP Socket实现客户与服务器简单通信

    在Linux平台下用C语言udp协议实现客户与服务器的简单通信与封装的实现 一.服务器端 1.新建CreateServer.c和CreateServer.h文件,服务器的创建代码在此实现,程序中封装了 ...

最新文章

  1. python 队列 一次取多个_Queue 队列模块-Python成为专业人士笔记
  2. Python 发送邮件 和 发送带附件邮件
  3. 设置vim语法高亮显示和自动缩进
  4. LeetCode 374. 猜数字大小(二分查找)
  5. SD卡支持大容量办法(转)
  6. C++---set/multiset用法介绍
  7. 【图像分割】基于matlab模糊聚类算法FCM图像分割【含Matlab源码 084期】
  8. moba的m是什么意思_moba游戏是什么
  9. jquery视频教程(jquery视频教程全集)
  10. KMeans聚类分析实战——如何把城市划分成不同的种类
  11. 教师评语计算机实验报告作业,作业实验报告评语大全
  12. NAT技术及NAT ALG
  13. 为什么产品经理都在学画原型?
  14. stm32中的或运算 ||
  15. lk:littlekernel-概述
  16. python如何下载安装glfw_Python之OpenGL笔记(1):窗口工具包GLFW的安装
  17. (Git/Github笔记)Git使用时错误记录
  18. linux线程池的使用
  19. 安全管家安卓_手机丢失后可能背负巨额债务,腾讯手机管家提醒注意手机安全防护 -...
  20. Python利用微软Azure免费的语音合成TTS源码分享

热门文章

  1. 转:设计模式趣味理解
  2. 自定义marker图标(icon)
  3. java毕业设计人人小说系统mybatis+源码+调试部署+系统+数据库+lw
  4. 删除 Windows10系统 “此电脑” 中的 “3D对象” 等文件夹
  5. 人工蜂群算法详解(附代码下载)
  6. 风投大师:揭秘创业与融资
  7. 每日一个爬虫练习:爬取喜马拉雅音频
  8. zerotire 实现穿透及异地组网
  9. GPT最新免费网站分享(持续更新)
  10. orgChart的简单使用,实现树状图、组织结构图结构