新 搞java
以前搞过一些jsp都是03年的事情了太久没弄java方面的东西最近要搞一个游戏服务端,因为服务器是linux系统,c++在linux下面开发没搞过,想到了java来做游戏服务端但是看了一下别人写的ServerSocket代码很困惑特此请教代码如下class .......{   public main....{
    ServerSocket server = new ServerSocket (10000);//我的理解是创建了一个ServerSocket实例并初始化其端口为10000
  while (true){
        Socket s = server.accept ();
   System.out.println ("Accepting Connection...n");
   new ServerThread (s).start ();
  }   }}
困惑在while里面如果我直接用ServerSocket这个东西来处理客户端的请求,为什么还要在循环里面不停的申明一个socket类型来接受server.accept的返回值?我看了一下accept的说明只是说这个服务从accpet开始,并返回一个什么来着,刚才看了忘记了另外即便是要为每个用户创建一个线程类来提高并发效率,那为什么在死循环里面要不同的创建s能不能通过accept的返回来判断是否需要创建呢另外我看了一下这个代码的ServerThread这个线程类,里面并没有start方法啊从哪里启动的请各位高手指点一下他为什么要这样写难道不能把serversocket直接置为侦听状态,等有请求的时候再在线程类里面建立一个属于serversocket的socket来负责与客户端通信吗?能不能不要一直死循环
因为刚接触,所以以上代码来自互联网,但是看了几个都用死循环做的我就不知道能不能用其他方式了另外我看的都是
br = new BufferedReader(new InputStreamReader(client.getInputStream()));
用流的方式来读取如果客户端发送的是二进制数据该怎么读取另外
     ps = new PrintStream(client.getOutputStream());
请问这行代码是往客户端发送数据吗?
因为我只看到了接收数据没看见socket的send动作
不知道该如何发请各位老大给指点一下才接触java编程2小时如果有说的不对的请各位老大多多指教
希望问题能够得到圆满解答
在线等

解决方案 »

  1.   

    Socket s = server.accept ();//到这一句,如果没有客户端socket连接,就会一直处于阻塞状态,有客户端连接了才会执行下面的语句,新建一个线程并启动,
    Thread里面有start() 方法,有run()方法,run方法是要线程执行的内容,执行start()方法后线程处于就绪状态,抢到时间片就会执行run方法。ServerThread类是自己写的方法,继承了Thread方法,虽然类体内没有写start(),但实际已经从父类继承来了ps只是创建一个对象
    ps.println()是发送数据的方法之一
      

  2.   

    二进制数据不太懂client.getInputStream()是获取的字节输入流InputStreamReader()桥转换器  把字节输入转成字符输入BufferedReader()字符输入流
      

  3.   

    不能先把一个ServerSocket置为监听状态吗?如果可以该怎么做
      

  4.   

    我仔细的看了一下那个线程类的代码
    里面的确没有start() 方法难道你说的有是指是thread自带就有吗
      

  5.   

    accept方法调用,这个线程就被挂起了。直到端口有request过来,accept方法才被返回。
    所以,这里必须是死讯坏,用于监听端口。而处理则交由其他线程类处理如果你不想用死循环,也可以采用非阻塞的Socket类。不过原理是一样的。如果是2进制数据,那么Reader结尾的装饰类都不能用了直接用byte数组来接吧。然后用FileOutputStream写入实体文件即可
      

  6.   

    这位老大刚才回复之前没看见你答案
    你一说我就明白了至于我说的用socket来接受二进制数据这块能不能给个代码我看一下我倒不用操作文件。我是要通过读取二进制数据后还原为比如String类型然后进行分析和判断在决定往客户端广播什么或者要决定是给所有用户广播还是对特定组广播还是对特定用户广播
      

  7.   

    我用的是eclipse的开发环境里面不能直接看到引入包方法的代码吗?如果可以怎么看我按着
    ctrl再点鼠标过去的只有方法的说名,我想看看具体实现怎么看
      

  8.   

    private void parseRequest(Socket socket) throws IOException {

    InputStream is = socket.getInputStream();

    if (is.available() == 0) {
    return;
    }

    byte[] lBuff = new byte[8192];
    int lRead = is.read(lBuff);
    byte[] lResp = new byte[lRead];
    System.arraycopy(lBuff, 0, lResp, 0, lRead);

    System.out.println(new String(lBuff, "UTF-8").trim());

    }这是我做WebSocket服务器时的代码,你可以参考下,8192作为一个缓冲区。(我这里只需要读取协议头,所以8192足够了)你这里可以加入一个循环
      

  9.   

    如何获得客户端连接成功后的句柄呢
    或者说客户端标示就是客户端的socket连接成功后,服务端应该能得到该socket的线程句柄在java里面如何获得
      

  10.   

    还是看一些简单的Soket入门书籍吧
      

  11.   

    http://blog.csdn.net/closewbq/archive/2010/07/21/5751738.aspx
    以前也是回答别人问题时候写的一个小例子。你可以看看。如果你以前做c++的,你应该听说过通过socket实现IOCP完成端口。虽然c++都是调用win32的东西能更好的实现,但是我觉得你理解这个应该不难!
      

  12.   

    楼上的你的博客我看了这个代码质量总算比网上看的那些demo质量好些总算有线程类,总算有线程同步但是还是没看出来哪里能得到客户端的socket线程句柄我不知道你们是如何区分的比如最简单的服务端变成应该是
    将serversocket(这个东西我觉得很像一个delphi的控件)置于监听状态然后当有客户端连接的时候(java里面就是当accept的时候)
    serversocket来处理这个请求,如果允许请求则把远程客户端的请求建立一个线程,当然这个线程中可以包含客户端的很多信息,其中可以包括客户端的socket句柄然后将这个客户端信息存放在服务端的一个维护用户列表信息里面,方便以后用假如A用的线程句柄为1000,B用户的句柄为1015,那么当B用户对A用户私聊的时候只需要在服务端的用户列表里面找到这个A用户的句柄信息,然后通过这个句柄可以由ServerSocket来像这个客户端信息发送数据
    我看了一下别人的代码有的用hashmap来存放的
    另外不知道楼上的老大提起了IOCP是何意在我看来你上面的代码好像没有用到类似线程池,内存池和IO重叠的部分仅仅应该是一个多线程的东西吧
      

  13.   

    应该说,如果要加入点对点,用HashMap<String(房建号), List<Thread>(房间内人的Socket长连接)>是比较简单直接的方法。ls的例子的确没有用到线程池。
      

  14.   

    我大概查阅了一下资料
    好像linux里面没有消息机制
    那样的话怎么能在linux里面实现回调函数?
    请各位高手指点
      

  15.   

    18楼的老大说的正和我意有没有demo代码给俺看看主要还是新手啊惭愧
      

  16.   

    首先ServerSocker.accept方法是阻塞的
    然后java I/O是基于流的,可以从Socket获得InputStream和OutputStream,然后用PrintStream包装起来(有更好用的方法)而不用管它是怎么样实现的,这正是java的强大之处
      

  17.   

    楼上的兄台一定是传说中的java fans了凡事有利就有弊他都帮你做完了就意味着自定义的机会就少了,就不那么灵活了而且我从来没质疑java的强大啊