socket多客户端连接服务器

原创 2016年06月01日 16:20:53

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
版权声明:本文为博主原创文章,未经博主允许不得转载。

linux下socket编程实现一个服务器连接多个客户端

使用socekt通信一般步骤     1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。     2)客户端:socker()建立...
  • Ctrl_qun
  • Ctrl_qun
  • 2016年09月13日 11:01
  • 6488

java Socket 一个服务器与多个客户端进行通信

在实现一个服务器与多个客户端进行通信的时候,此时就需要引入多线程编程,用多个线程同时为多个客户提供服务,这时提高服务器你并发性能最长用的手段,服务器的主线程负责接收客户的连接,每次接收到一个客户连接就...
  • WannerWang
  • WannerWang
  • 2015年10月15日 17:50
  • 1054

github上的学习材料一:前端涉及的所有知识体系

前面分享了前端入门资源汇总,今天分享下前端所有的知识体系。 个人站长对个人综合素质要求还是比较高的,要想打造多拉斯自媒体网站,不花点心血是很难成功的,学习前端是必不可少的一个环节, 当然你不一定要...
  • u011467458
  • u011467458
  • 2016年09月17日 20:58
  • 2151

socket实现多个客户端连接在一个服务器上

1、使用socekt通信一般步骤     1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。     2)客户端:socker()...
  • dazhong159
  • dazhong159
  • 2012年08月30日 15:06
  • 37265

linux socket的多线程编成来实现多个客户端的连接

在socket的网络编程中常常采用多线程的方法来进行与多个客户端的通信,使服务器与多个客户端的通信并发、并行地进行。相比于多进程,多线程的好处是共用一块内存空间,下面我们来看一个简单的例子,就是多个客...
  • gepanqiang3020
  • gepanqiang3020
  • 2017年06月24日 12:00
  • 368

linux下socket实现多个客户端与服务器的通信

学习完《UNIX环境高级编程》套接字一章的内容之后,自己实现了单个客户端与服务器的通信程序,后面想想要是多个客户端如何与服务器通信呢?这就有了这篇文章。 这里采用的是用多线程实现多客户端与服务器的通...
  • wdlove58
  • wdlove58
  • 2016年09月25日 13:30
  • 3316

Linux c==TCP的多个客户端连接服务器 (20)

通过父子进程实现TCP的多个客户端连接服务器 tcp_sever_fork.c#include #include #include #include #include ...
  • weirdosick
  • weirdosick
  • 2016年11月25日 17:07
  • 1061

C#Socket编程多客户端基于同一服务端通信

对于Socket编程,网上资料、博文一抓一大把,不过大多数都是简单讲解单客户端和服务端通信的实例,这里主要给大家展现一下在.net平台上用窗体程序实现的过程,不过比较有特点的是会告诉大家如何实现不同客...
  • Yujie_Yang
  • Yujie_Yang
  • 2016年12月14日 21:30
  • 3410

linux socket网络编程:fcntl select(多个客户端连接服务器端情形)

一、引言     在实际情况中,人们往往遇到多个客户端连接服务器端的情况。由于之前介绍的函数如connect,recv,send等都是阻塞性函数,若资源没有充分准备好,则调用该函数的进程将进入睡眠状...
  • YEYUANGEN
  • YEYUANGEN
  • 2011年08月30日 13:39
  • 9670

C++ Socket 一个服务器 多个客户端 (阻塞式)

服务端 ServerNet.h#pragma once #include #include #include #include #include #include #include #incl...
  • qq_17543531
  • qq_17543531
  • 2016年08月11日 21:47
  • 4733
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:socket多客户端连接服务器
举报原因:
原因补充:

(最多只允许输入30个字)