JAVA中,假设一个服务器和一个客户机通信。采用UDP,我已经实现了无阻塞通信。但改成TCP就不行了。客户机和服务机只能进行一次通信,后来两者发的信息均不能到达对方的屏幕上。编程思路和用UDP协议差不多,在服务器里面,开一个线程专门发,开一个线程专门收。客户机同。不知道问题在哪。我把源码帖在下面!请有耐心的朋友帮我看下(可以调试下的)!
×××××××以下是客户机的代码:import java.io.*;
import java.net.*;
class Clientm
{
ServerSocket ss;
Socket socket;
BufferedReader br2,br1;
PrintWriter pw;
String line=null;

public Clientm()
{
try

{
//ss=new ServerSocket(9999);
socket=new Socket("127.0.0.1",9999);
 br1=new BufferedReader(new InputStreamReader(System.in));
pw=new PrintWriter(socket.getOutputStream());
br2=new BufferedReader(new InputStreamReader(socket.getInputStream()));

}
catch(IOException ex)
{
ex.printStackTrace();
}
}


public static void main(String args[])
{
Clientm cm=new Clientm();
Sendc sends1=cm.new  Sendc();
Receivec receives1=cm.new Receivec();
sends1.start();
receives1.start();

}




class Sendc extends Thread  //现在才知道内部类真是他妈的强大!
{


public void run()
{
try
{

 line=br1.readLine();
 while(!line.equals("bye"))
 {
 System.out.println("client is sending.....");
 pw.println(line);
 pw.flush();

 line=br1.readLine();
 }
 
 br1.close();
 br2.close();
 pw.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}

} class Receivec extends Thread
{


public void run()
{
try
{

System.out.println("Server Says:"+br2.readLine());


}
catch(IOException ex)
{
ex.printStackTrace();
}

}
}
}×××××××××××××以下是服务器的代码
import java.io.*;
import java.net.*;
class Serverm
{
ServerSocket ss;
Socket socket;
BufferedReader br2,br1;
PrintWriter pw;
String speaking=null;

public Serverm()
{
try

{
ss=new ServerSocket(9999);
socket=ss.accept();
 br1=new BufferedReader(new InputStreamReader(System.in));
pw=new PrintWriter(socket.getOutputStream());
br2=new BufferedReader(new InputStreamReader(socket.getInputStream()));
 
}
catch(IOException ex)
{
ex.printStackTrace();
}
}


public static void main(String args[])
{
Serverm sm=new Serverm();
Sends sends1=sm.new  Sends();
Receives receives1=sm.new Receives();
sends1.start();
receives1.start();

}




class Sends extends Thread  
{




public void run()
{
try
{
speaking=br1.readLine();
 while(!speaking.equals("bye"))
 {
 System.out.println("server is sending.....");
 pw.println(speaking);
 pw.flush();

 speaking=br1.readLine();
 }
 System.out.println("connection is closed");
 
 br1.close();
 br2.close();
 pw.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}

} class Receives extends Thread
{


public void run()
{
try
{

System.out.println("server is receving.....");
System.out.println("Client Says:"+br2.readLine());





}
catch(IOException ex)
{
ex.printStackTrace();
}

}
}
}

解决方案 »

  1.   

    socket=ss.accept(); 
    br1=new BufferedReader(new InputStreamReader(System.in)); 
    pw=new PrintWriter(socket.getOutputStream()); 
    br2=new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    这段代码是要放到线程中去的,因为每accept一次就能从列队中读去一条信息
    有必要的话去网上搜索例子代码看看就会更明白了
      

  2.   

    问题蛮多额 明天有时间再来看看
    刚刚看了下 感觉应该 socket=ss.accept();  要给一个循环
      

  3.   

    无阻塞sock编程,可以用nio啊
    给个实例
    import java.io.*; //引入Java.io包
    import java.net.*; //引入Java.net包
    import java.nio.channels.*; //引入Java.nio.channels包
    import java.util.*; //引入Java.util包
    public class TestServer implements Runnable{
    /*** 服务器Channel对象,负责接受用户连接
    */
    private ServerSocketChannel server;
    /**
    * Selector对象,负责监控所有的连接到服务器的网络事件的发生
    */
    private Selector selector;
    /**
    * 总的活动连接数
    */
    private int activeSockets;
    /**
    * 服务器Channel绑定的端口号
    */
    private int port ;
    /**
    *
    * 构造函数
    */
    public TestServer()throws IOException
    {
    activeSockets=0;
    port=9999;//初始化服务器Channel绑定的端口号为9999
    selector= Selector.open();//初始化Selector对象
    server=ServerSocketChannel.open();//初始化服务器Channel对象
    ServerSocket socket=server.socket();//获取服务器Channel对应的//ServerSocket对象
    socket.bind(new InetSocketAddress(port));//把Socket绑定到监听端口9999上
    server.configureBlocking(false);//将服务器Channel设置为非阻塞模式
    server.register(selector,SelectionKey.OP_ACCEPT);//将服务器Channel注册到
    Selector对象,并指出服务器Channel所感兴趣的事件为可接受请求操作
    }
    public void run()
    {
    while(true)
    {
    try
    {
    /**
    *应用Select机制轮循是否有用户感兴趣的新的网络事件发生,当没有* 新的网络事件发生时,此方法会阻塞,直到有新的网络事件发生为止
    */
    selector.select();}
    catch(IOException e)
    {
    continue;//当有异常发生时,继续进行循环操作
    }
    /**
    * 得到活动的网络连接选择键的集合
    */
    Set<SelectionKey> keys=selector.selectedKeys();
    activeSockets=keys.size();//获取活动连接的数目
    if(activeSockets==0)
    {
    continue;//如果连接数为0,则继续进行循环操作
    }
    /**/**
    * 应用For—Each循环遍历整个选择键集合
    */
    for(SelectionKey key :keys)
    {
    /**
    * 如果关键字状态是为可接受,则接受连接,注册通道,以接受更多的*
    事件,进行相关的服务器程序处理
    */
    if(key.isAcceptable())
    {
    doServerSocketEvent(key);
    continue;
    }
    /**
    * 如果关键字状态为可读,则说明Channel是一个客户端的连接通道,
    * 进行相应的读取客户端数据的操作
    */
    if(key.isReadable())
    {
    doClientReadEvent(key);continue;}
    /**
    * 如果关键字状态为可写,则也说明Channel是一个客户端的连接通道,
    * 进行相应的向客户端写数据的操作
    */
    if(key.isWritable())
    {
    doClinetWriteEvent(key);
    continue;
    }
    }
    }
    }/**
    * 处理服务器事件操作
    * @param key 服务器选择键对象
    */
    private void doServerSocketEvent(SelectionKey key)
    {
    SocketChannel client=null;
    try
    {
    ServerSocketChannel server=(ServerSocketChannel)key.channel();
    client=server.accept();
    if(client==null)
    {
    return;
    }
    client.configureBlocking(false);//将客户端Channel设置为非阻塞型
    /**/**
    * 将客户端Channel注册到Selector对象上,并且指出客户端Channel所感
    * 兴趣的事件为可读和可写
    */
    client.register(selector,SelectionKey.OP_READ|SelectionKey.OP_READ);
    }catch(IOException e)
    {
    try
    {
    client.close();}catch(IOException e1){}
    }
    }
    /**
    * 进行向客户端写数据操作
    * @param key 客户端选择键对象
    */
    private void doClinetWriteEvent(SelectionKey key)
    {
    代码实现略;
    }
    /**
    * 进行读取客户短数据操作
    * @param key 客户端选择键对象
    */
    private void doClientReadEvent(SelectionKey key)
    {
    代码实现略;
    }
    }从上面对代码可以看出,使用非阻塞性I/O进行并发型服务器程序设计分三个部分:1.
    向Selector对象注册感兴趣的事件;2.从Selector中获取所感兴趣的事件;3.根据不同的事件进
    行相应的处理。
    结语 
    通过使用NIO 工具包进行并发型服务器程序设计,一个或者很少几个Socket 线程就可
    以处理成千上万个活动的Socket 连接,大大降低了服务器端程序的开销;同时网络I/O 采取
    非阻塞模式,线程不再在读或写时阻塞,操作系统可以更流畅的读写数据并可以更有效地向
    CPU 传递数据进行处理,以便更有效地提高系统的性能
      

  4.   

    看了下哇  是这样的额
    如果你要在server也实现可以读取system.in的话  那么你的client也必须去实现一个socketserver  
    其实你想做的是一个p2p的通讯哇  就是server是server也是client 同时client是client也是一个server 
    所以 在client端 你需要加一个socketserver去实现这个p2p的功能但是一般来说  不是那么写的哇  因为我觉得你的本意不是写p2p一般来说  是一个Main线程  然后再加一个Thread
    Main里面一个socket.getInputStream
    Thread里面一个socket.getOutStream这样就可以啦
      

  5.   

     好象不需要在client里加serversocket呀,我现在假设就一个服务器,一个客户机,客户机连到服务器上后,进行通信,即互发数据!为什么还要将客户机加一个serversocket呢? 个人认为,三楼用了一种很强大、更为先进的方法,我现在也转型研究NIO了。 一楼的解决方法是接着我的思路走了,也蛮好。当我把三楼的NIO搞懂后,有空再把一楼的方法研究下。