最近闲时练习了多线程socket,也在网上搜索看了一些贴子,于是做了练了练,却发现总得到不自己期待的结果。
目的:多个客户端同时请求服务器端,然后向客户传送一个文件,即想达多非阻塞的响应请求。不是一个接一个处理,而是同时处理。我简单的描述下,具体的在附件里:
public class CcMyServer {
private  ServerSocket serverSocket=null; 
    private  ExecutorService executorService;//线程池
    private final  int POOL_SIZE=10;//单个CPU线程池大小
    
    public CcMyServer() throws IOException{
     serverSocket = new ServerSocket(5556);
     executorService=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
     System.out.println("服务器端开始");
    }
    
    public void service(){
     int i = 0;
Socket socket = null;
while (true) {
try {
socket=serverSocket.accept();
System.out.println("看看执行多少次" + (++i));
executorService.execute(new CcHandler(socket));
} catch (IOException e) {
e.printStackTrace();
}
}
    }
    
public static void main(String[] args) throws IOException {
new CcMyServer().service();
}
}public class CcHandler  implements Runnable{
private Socket socket;
    public CcHandler(Socket socket){
        this.socket=socket;
    }
    
public void run() {
//....代码省略..
}
 }public class CcMultiUser {
private static String str="";
public static void main(String[] args){
int numTasks = 10;
    ExecutorService exec = Executors.newCachedThreadPool();
    for (int i = 0; i < numTasks; i++) {
     str=i+"QQ";
     System.out.println(str);
        exec.execute(createTask(i));
        System.out.println("==="+i+"==");
        }
}
    private static Runnable createTask(final int taskID) {
      return new Runnable() {
             public void run() {
                         
//....代码省略..
         };
}

解决方案 »

  1.   

    我刚上传的附件哪去了?晕死,怎么还不能修改啊?我的msn:[email protected]在线交流
      

  2.   

    线程池没弄过,在客户端有必要用线程池去处理??
    不知道加入线程池中的线程要不要start来启动的。
    代码没问题。
      

  3.   


    莫非我真写的不是非阻塞的?不可能吧。你在仔细看看。我也是参考了一些资料做的也。最近才接触多线程socket。CcMultiUser类是客户端模拟多个客户同时请求服务器CcMyServer 现在遇到的问题就是:服务器启动正常,当客户端启动时什么反应都没有(程序无异常),就像请求后没有返回结果一样。
    最想知道的是请求后为什么没有响应。
      

  4.   

    我把server的助手类CcHandler与客户端类CcMultiUser 补充完整,或者传完整附件import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.net.Socket;public class CcHandler  implements Runnable{
    private Socket socket;
        public CcHandler(Socket socket){
            this.socket=socket;
        }
        
    public void run() {
    try {
    // 选择进行传输的文件
    String filePath = "D:\\aaa.zip";

    File fi = new File(filePath);
    // public Socket accept() throws
    // IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。 writerLog("文件长度:" + (int) fi.length()+"建立socket链接");

    DataInputStream dis = new DataInputStream(new BufferedInputStream(
    socket.getInputStream()));
    dis.readByte(); DataInputStream fis = new DataInputStream(new BufferedInputStream(
    new FileInputStream(filePath)));
    DataOutputStream ps = new DataOutputStream(socket.getOutputStream());
    // 将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java
    // 4th里有现成的代码。
    ps.writeUTF(fi.getName());
    ps.flush();
    ps.writeLong((long) fi.length());
    ps.flush();
    writerLog("开始");
    int bufferSize = 8192;
    byte[] buf = new byte[bufferSize]; while (true) {
    int read = 0;
    if (fis != null) {
    read = fis.read(buf);
    } if (read == -1) {
    break;
    }
    ps.write(buf, 0, read);
    }
    ps.flush();
    // 注意关闭socket链接哦,不然客户端会等待server的数据过来,
    // 直到socket超时,导致数据不完整。
    fis.close();
    writerLog("文件传输完成");
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    } }
    }

      public static void writerLog(String logs) throws IOException{
         File file =new File("D:/socket.txt");
         if(!file.exists()){
    file.createNewFile();
         }
         FileWriter writer = new FileWriter(file, true);
         writer.write(logs+"\r\n");
         writer.close();
        }
    }
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileOutputStream;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;public class CcMultiUser {
    private static String str="";
    public static void main(String[] args){
    int numTasks = 10;
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < numTasks; i++) {
         str=i+"QQ";
         System.out.println(str);
            exec.execute(createTask(i));
            System.out.println("==="+i+"==");
            }
    }
        private static Runnable createTask(final int taskID) {
          return new Runnable() {
                 public void run() {
                  try {
              System.out.println("客户端开始执行");
              Socket socket = new Socket("localhost", 5556);
             
              // 本地保存路径,文件名会自动从服务器端继承而来。
              String savePath = "D:\\XX"+str;
              int bufferSize = 8192;
              byte[] buf = new byte[bufferSize];
              int passedlen = 0;
              long len = 0;
             
              DataInputStream is = new DataInputStream(new BufferedInputStream(
              socket.getInputStream()));
              savePath += is.readUTF();
              DataOutputStream fileOut = new DataOutputStream(
              new BufferedOutputStream(new BufferedOutputStream(
              new FileOutputStream(savePath))));
              len = is.readLong();
             
              System.out.println("文件的长度为:" + len + "\n");
              System.out.println("开始接收文件!" + "\n");
             
              while (true) {
              int read = 0;
              if (is != null) {
              read = is.read(buf);
              }
              passedlen += read;
              if (read == -1) {
              break;
              }
              // 下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比
              System.out.println("文件接收了" + (passedlen * 100 / len) + "%\n");
              fileOut.write(buf, 0, read);
              }
              System.out.println("接收完成,文件存为" + savePath + "\n");
             
              fileOut.close();
              } catch (Exception e) {
              System.out.println("接收消息错误" + "\n");
              return;
              }
                 }         };
    }
    }
      

  5.   

    你这写的socket本身是阻塞的,只不过使用多线程能够达到同时与多个客户端通讯。
      

  6.   

    目的:多个客户端同时请求服务器端,然后向客户传送一个文件,即想达多非阻塞的响应请求。不是一个接一个处理,而是同时处理。
    LZ你这个目的似乎矛盾啊
    想达到非阻塞,还不能一个一个处理,要同时处理
    呵呵
    非阻塞就用NIO了,其实非阻塞本来即时性可能会差一点,因为这个非阻塞使用几个线程来控制n个线程的
    它有好多开源框架
    像MINA啦
    好多基本功能它都已经实现了
    你只要实现你的业务逻辑就好了
    网上资料很多,LZ可以搜搜看