首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

Socket菜鸟提问

2013-12-04 
Socket初学者提问-------------首先声明:我在控制台上编程,目的:能够使得SocketTest(客户端)和ClientTest(

Socket初学者提问
-------------
首先声明:
    我在控制台上编程,
目的:
    能够使得SocketTest(客户端)和ClientTest(服务端)互相通信
自己判断:
    SocketTest可以单独和telnet通信,所以问题锁定在ClientTest上!
-------------
请看代码:


import java.net.* ;
import java.util.* ;
import java.io.* ;
public class ClientTest{
public static void main(String[]args){
long start = System.currentTimeMillis() ;
start() ;
long end = System.currentTimeMillis() ;
System.out.println("总共连接时间:"+(end-start)+"(ms)") ;
}
public static void start(){
try{
   Socket s = new Socket() ;
   try{
s.connect(new InetSocketAddress("127.0.0.1",9000),10000);//连接不得超过10秒钟
OutputStream out  = s.getOutputStream();
InputStream  in   = s.getInputStream () ;

boolean done = false ;
while(!done)
{
Scanner serverSay = new Scanner(in);
String line = "" ;
/***
 * 目的:一开启Client,就先尝试接收服务端发过来的信息
 * 问题:运行程序,并未接到SocketTest服务端传来的提示信息,
 *       我自己调试,发现貌似出现了阻塞,hasNextLine()阻塞了,
 *       导致接收不到数据,但我不知道怎么改?
 */
while( serverSay.hasNextLine() ){
line = serverSay.nextLine() ;
System.out.println(line);
}

System.out.print("我说 : ") ;
String iStr = consoleRead(null) ;        //说话的内容
byte[] serverSayBytes = iStr.getBytes(); //把数据组成字节流
out.write(serverSayBytes) ;         //发送数据
out.flush();
}// end while
   }//end try 
   finally{
s.close() ; 
   }
}//end try
catch(Exception err){
err.printStackTrace() ;
}
}
/**
 * @param: 在输入控制台之前,控制台出现的提示语
 * @return:在控制台输入的语句,以'!'、'!'、'\n'结束
 */
public static String consoleRead(String prompt/*输入控制台前,控制台的提示语*/)
throws IOException{
if( null != prompt )
System.out.println(prompt);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine() ;
return str ;
}
}

-------------
再次声明:
    我在控制台上编程,
目的:
    能够使得SocketTest(客户端)和ClientTest(服务端)互相通信
自己判断:
    SocketTest可以单独和telnet通信,所以问题锁定在ClientTest上!
-------------
【服务端代码,我自己放在1楼,不然问题太长大家不愿看】

提问:
问题1:
     请各位看看问题的ClientTest.java第30行,上面的注释提出了问题。

问题2:
      如果把30行开始的代码
                              while( serverSay.hasNextLine() ){
line = serverSay.nextLine() ;
System.out.println(line);
      }
      改成:
                              //while( serverSay.hasNextLine() ){
line = serverSay.nextLine() ;
System.out.println(line);
      //}
      就能接到SocketTest数据,虽然只能接到一条数据,
      但是,写完数据后,却无法发送回服务端SocketTest,非要Ctrl+C关闭程序时才能发送数据!
      我推测是写的数据被放进了BUF缓存,可是我都out.flush()了?
      所以,依然不解 ... 求指教
【服务端代码,我自己放在1楼,不然问题太长大家不愿看】
[解决办法]
下面是现实客户端给服务端发送信息,并在服务端显示出来(用Eclipse)
服务端

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ServerTread extends Thread
{
private Socket socket;

public ServerTread(Socket socket)
{
this.socket = socket;
}

@Override
public void run()
{
try
{


InputStream is = socket.getInputStream();

while (true)
{
byte[] b = new byte[1024];

int length = is.read(b);

String str = new String(b,0,length);

System.out.println(str);
}
}
catch (IOException e)
{
e.printStackTrace();
}


}
}



客户端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class ClientTread  extends Thread
{
private Socket socket;

public ClientTread(Socket socket)
{
this.socket = socket;
}

@Override
public void run()
{
try
{
OutputStream out = socket.getOutputStream();

while (true)
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

String line = br.readLine();

out.write(line.getBytes());
}
}
catch (IOException e)
{
e.printStackTrace();
}

}

}



服务端测试类

import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket = new ServerSocket(5000);

while (true)
{
Socket socket = serverSocket.accept();

new ServerTread(socket).start();
}
}
}


客户端测试类

import java.net.Socket;

public class ClientTest
{
public static void main(String[] args) throws Exception
{
Socket socket = new Socket("127.0.0.1", 5000);

new ClientTread(socket).start();
}
}


[解决办法]
这里有个socket的例子,你可以看看:
http://kanpiaoxue.iteye.com/admin/blogs/1956800
[解决办法]
引用:
Quote: 引用:

这里有个socket的例子,你可以看看:
http://kanpiaoxue.iteye.com/admin/blogs/1956800


你好,你这里有好多文章,看哪一篇呢 ?


 java net 编程(Socket,netty) 
[解决办法]
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

这里有个socket的例子,你可以看看:
http://kanpiaoxue.iteye.com/admin/blogs/1956800


你好,你这里有好多文章,看哪一篇呢 ?


 java net 编程(Socket,netty) 


可是我的代码错在哪里呢?
我的2个问题就在那 ... 
可是真心不懂了!

不是都说OuputStream负责发送,InputStream负责接受么?
那么我用Scanner(InputStream )后,scanner.hasNextLine()为什么就接收不了所有的?何况我还flush了。
为什么我的OutputStream无法发送,非要关闭程序才发送?

我希望你能指点我一下 ... 可以么?


你的具体的代码我没看。不过看了你的问题的描述,推测如下:
你的服务器端的 OuputStream write数据的时候,在里面添加\n了么?
因为你的clietn像是readLine()读取的数据,他需要\n来表示新的一行。
同时,你的client端发送数据给Server的时候,如果server也是用的readLine(),那么你client发送数据的时候,也需要添加\n来结尾,表示你的发送一个line已经结束。
为啥会阻塞?应该就是你没有添加\n,造成你的程序认为读取的流文件没有结束,而继续等待。
[解决办法]

while( serverSay.hasNextLine() ){
                    line = serverSay.nextLine() ;
                    System.out.println(line);
                }
                 
                System.out.print("我说 : ") ;

也就是说你的“我说 :”没有执行,依然阻塞在 serverSay.hasNextLine() 这里。问题的地方都找到了,原因应该也就出来了。看你的服务器输出,应该是你的服务器输出有问题,造成serverSay.hasNextLine()没结束,依然在等待。
解决这种client和server的通讯的关键在于:协议的一致性。比如client和server都采用\n表示内容的结束,都采用readline读取数据。这样协议是一致的,就不会出现你这种阻塞的问题。阻塞?为什么呢?就是通讯的协议不一致。
[解决办法]

OutputStream outStream = incoming.getOutputStream();
InputStream inStream = incoming.getInputStream();
outStream.write("Hello ! Enter BYE to exit .\n".getBytes());
outStream.write("me[c]:\n".getBytes());

outStream.flush();//添加这行代码

[解决办法]
我觉得你应该把 InputStream  in   = s.getInputStream () ;写进循环中,因为这行代码,他只能发送一次!再次发送语句的话,你应该在写这样的一个语句!在服务器那端也一样
[解决办法]
上面的代码有些问题,我做了一下调整,如下:



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

/**
 * <pre>
 * @author kanpiaoxue
 * Date 2013-11-27
 * </pre>
 */
public class TalkSocketServer {
private static final Logger LOGGER = Logger
.getLogger(TalkSocketServer.class);

class Producer implements Runnable {
private BlockingQueue<Socket> queue;
private ServerSocket server;

public Producer(String name, BlockingQueue<Socket> queue, int port) {
super();
this.queue = queue;
try {
Thread.currentThread().setName(name);
server = new ServerSocket(port);
} catch (IOException e) {
LOGGER.error("Error:" + e.getMessage(), e);
}
}

@Override
public void run() {
LOGGER.info(server + " start to work.");
while (true) {
try {
queue.put(server.accept());
} catch (Exception e) {
LOGGER.error("Error:" + e.getMessage(), e);
}
}

}
}

class Consumer implements Runnable {

private BlockingQueue<Socket> queue;

public Consumer(String name, BlockingQueue<Socket> queue) {
super();
this.queue = queue;
Thread.currentThread().setName(name);
}

@Override
public void run() {
while (true) {
Socket socket = null;
try {
socket = queue.take();
consume(socket);
} catch (Exception e) {
LOGGER.error("Error:" + e.getMessage(), e);
} finally {
if (null != socket) {
try {
socket.close();
LOGGER.info(socket + " closed.");
} catch (IOException e) {
}
}
}
}

}

private void consume(Socket socket) throws Exception {
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
sendMsg(writer, "Welcome to talking system!");
for (String request = reader.readLine(); null != request; request = reader
.readLine()) {
if (request.trim().equalsIgnoreCase("bye")) {
sendMsg(writer, "Good bye " + socket + " !");
closeAll(writer, reader, socket);
break;
}
sendMsg(writer, socket + "You say [" + request + "] to me.");
}

// close all resource
closeAll(writer, reader, socket);
}

private void closeAll(Writer writer, Reader reader, Socket socket)
throws IOException {
IOUtils.closeQuietly(writer);
IOUtils.closeQuietly(reader);
socket.close();
}

private void sendMsg(PrintWriter writer, String msg) {
writer.println(msg);
writer.flush();
}
}

/**
 * @param args
 */
public static void main(String[] args) {
TalkSocketServer t = new TalkSocketServer();
ExecutorService exec = Executors.newCachedThreadPool();
BlockingQueue<Socket> queue = new LinkedBlockingQueue<Socket>();
int port = 7777;
exec.execute(t.new Producer("producer", queue, port));
for (int i = 0, j = Runtime.getRuntime().availableProcessors() * 2; i < j; i++) {
exec.execute(t.new Consumer("consumer-" + i, queue));
}
exec.shutdown();
}

}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

/**
 * 
 * @author kanpiaoxue
 * 
 */
public class TestSocketClient {
private static final Logger LOGGER = Logger
.getLogger(TestSocketClient.class);

private Socket socket;

/**
 * @param host
 * @param port


 */
public TestSocketClient(String host, int port) {
super();
try {
socket = new Socket(host, port);
LOGGER.info(socket + " start to work.");
} catch (Exception e) {
LOGGER.error("Error:" + e.getMessage(), e);
}
}

public void talk() throws Exception {
BufferedReader localReader = new BufferedReader(new InputStreamReader(
System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
System.out.println(reader.readLine());
System.out.println("enter message :");
for (String request = localReader.readLine(); null != request; request = localReader
.readLine()) {
sendMsg(writer, request);
System.out.println(reader.readLine());
if (request.trim().equalsIgnoreCase("bye")) {
break;
}
}

IOUtils.closeQuietly(localReader);
socket.close();
}

private void sendMsg(PrintWriter writer, String msg) {
writer.println(msg);
writer.flush();
}

/**
 * @param args
 */
public static void main(String[] args) {
try {
new TestSocketClient("localhost", 7777).talk();
} catch (Exception e) {
LOGGER.error("Error:" + e.getMessage(), e);
}

}

}


[解决办法]
client里面的代码,发现几个资源没有关闭。下面的代码进行了关闭。

大致思路就是分两个socket,多线程实现。
源码如下:
服务端代码:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class SocketTest {
    public static void main(String[] args) {
        time();
    }

    public static void time() {
        long start = System.currentTimeMillis();
        // 专门负责向socket中写数据
        Socket writeSocket = null;
        // 专门负责从socket中读数据
        Socket readSocket = null;
        try {
            ServerSocket serverS = new ServerSocket(9000);
            System.out.println("---等待客户端连接---");
            // 服务端写操作对应客户端端读操作的socket
            writeSocket = serverS.accept();
            // 服务端读操作对应客户端读操作的socket
            readSocket = serverS.accept();


            System.out.println("---开始接收客户端消息---");

            // 读客户端信息
            FutureTask<Integer> readFuture = new FutureTask<Integer>(new ReadFromSocket(readSocket));
            new Thread(readFuture).start();
            // 写服务端信息
            FutureTask<Integer> writeFuture = new FutureTask<Integer>(new WriteToSocket(
                    writeSocket, "Server"));
            new Thread(writeFuture).start();

            // 通过future的get操作,使线程处于持有状态,从而线程没有返回就不会结束
            if (0 == readFuture.get() && 0 == writeFuture.get()) {
                System.out.println("正常结束");
            } else {
                System.out.println("异常结束");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭各种资源的正确流程
            try {
                if (null != writeSocket) {
                    writeSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("总共连接时间:" + (end - start) + "(ms)");
    }

}


客户端代码:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ClientTest {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        start();
        long end = System.currentTimeMillis();
        System.out.println("总共连接时间:" + (end - start) + "(ms)");
    }

    public static void start() {
        // 专门负责从socket中读数据
        Socket readSocket = new Socket();
        // 专门负责向socket中写数据
        Socket writeSocket = new Socket();
        try {
            // 客户端读操作对应服务端写操作的socket
            readSocket.connect(new InetSocketAddress("127.0.0.1", 9000), 10000);// 连接不得超过10秒钟
            // 客户端写操作对应服务端读操作的socket
            writeSocket.connect(new InetSocketAddress("127.0.0.1", 9000), 10000);// 连接不得超过10秒钟
            // 读服务端信息
            FutureTask<Integer> readFuture = new FutureTask<Integer>(new ReadFromSocket(readSocket));
            new Thread(readFuture).start();


            // 写客户端信息
            FutureTask<Integer> writeFuture = new FutureTask<Integer>(new WriteToSocket(
                    writeSocket, "Client"));
            new Thread(writeFuture).start();

            // 通过future的get操作,使线程处于持有状态,从而线程没有返回就不会结束
            if (0 == readFuture.get() && 0 == writeFuture.get()) {
                System.out.println("正常结束");
            } else {
                System.out.println("异常结束");
            }
        }// end try
        catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭各种资源的正确流程
            try {
                if (null != readSocket) {
                    readSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


写socket线程类:
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Callable;

public class WriteToSocket implements Callable<Integer> {

    // 可用的Socket链接
    private Socket socket;

    // 角色
    private String role;

    public WriteToSocket(Socket socket, String role) {
        this.socket = socket;
        this.role = role;
    }

    @Override
    public Integer call() throws Exception {
        // 合法性判断
        if (null == socket 
[解决办法]
 !socket.isConnected()) {
            System.out.println("非法的Socket链接!");
            return -1;
        }
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            Scanner sc = new Scanner(System.in);
            String tmp = null;
            for (; socket.isConnected() && !socket.isClosed();) {
                tmp = sc.nextLine();
                System.out.print("I say:" + tmp + System.getProperty("line.separator"));
                bw.write(role + " say:" + tmp);
                bw.newLine();
                bw.flush();


                if (tmp.endsWith("BYE")) {
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println("Write---IO异常");
            e.printStackTrace();
            return -1;
        } finally {
            // 关闭各种资源的正确流程
            if (null != socket) {
                socket.close();
            }
            try {
                if (null != bw) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return 0;
    }
}


读socket线程类:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.concurrent.Callable;

public class ReadFromSocket implements Callable<Integer> {

    // 可用的Socket链接
    private Socket socket;

    public ReadFromSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public Integer call() throws Exception {
        // 合法性判断
        if (null == socket 
[解决办法]
 !socket.isConnected()) {
            System.out.println("非法的Socket链接!");
            return -1;
        }
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while (!socket.isClosed() && socket.isConnected() && null != (line = br.readLine())) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Read---IO异常");
            e.printStackTrace();
            return -1;
        } finally {
            // 关闭各种资源的正确流程
            if (null != socket) {
                socket.close();
            }
            try {
                if (null != br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();


            }
        }
        return 0;
    }

}

热点排行