【第21期】观点:人工智能到底用 GPU?还是用 FPGA?

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

相关文章推荐

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

1、使用socekt通信一般步骤     1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。     2)客户端:socker()...

【TCP通信】多客户端连接一个服务器端总结

Windows下TCP通信,多个客户端连接服务器端。 一、服务器端流程实现如下: 1、通过socket函数,创建基于流式类型的socket,可名为serverSocket; 2、调用bind函数...
  • LW_HM
  • LW_HM
  • 2013-02-25 22:04
  • 7658

Android客户端,PC服务器,Socket连接所遇到的问题

这两天在编写 Socket客户端,服务器

socket编程(三)--服务器端实现多线程处理客户端请求并且将客户请求放在连接池中

需求:通socket编程(一)的需求 该实例中,客户端可能会有多个,服务器的处理器也会有多个,该情形类似于消费者在超市结账的过程, 假设固定有5个收银员,而消费者不确定: 如果开始没有消费者来结账,那么所有的收银员都处于等待状态; 如果有一个消费者来结账,那么随即会有一个收银员来处理,其他的收银员仍处于等待状态; 如果有大于一个小于6个的消费者来结账,那么收银员都会随即进行处理; 如果有大于5个的消费者在等待,就需要排队了(这也就是要说的连接池即客户端的请求链接放置的地方,把客户请求放在这个池

Linux下网络socket编程——实现服务器(select)与多个客户端(epoll)通信

一、关于socket通信服务器端工作流程: 调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址绑定 调用listen()函数监听socket() 函数创建的套...

windows如何获取连接远程socket(客户端)的ip地址,使用accept或者getpeername

 原文:http://blog.csdn.net/gukesdo/article/details/6889594   #include &lt;iostream&gt; #include
  • aigo
  • aigo
  • 2013-07-13 23:19
  • 6029
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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