是不是把 Socket socket = serverSocket.accept(); 这行代码 写在while循环外面了
你应该在客户端进行输出流完成之后就应该socket.shutdownOutput();而不是在最后才执行
try { //如果不设置等待时间,服务端已经关闭了,客户端还没有来得及读取这个响应,从而报错 System.out.println("先不要关闭"); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
我将你的代码中这个去掉,客户端是可以接收到服务端信息的.
找到原因来了,问题在于服务器端是用来BufferedReader的readLine函数,这个函数只用在读到换行符的时候才会结束,不然会一直是阻塞的状态。而我这里发送的时候没有加上换行符就会产生阻塞的现象,而我关闭了输出流,就等与强制结束了readLIne函数的进程,所以也能解决问题。
客户端是关闭输出流socket.shutdownOutput();
要先把连接关闭再运行,点击终止按钮
你把socket.shutdownInput写到While结构的后面,就不会出现了。同样的Client也是,我猜测:socket的这个方法,是优先级高的,应该先关掉,如果后置,就会重新检验Outputstream等等,结果,就悲剧了。
package CStest;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;import java.util.Scanner;public class ClientTest { public static void main(String[] args) { try { //创建客户端与服务器连接,并向服务器提示已连接 Socket socket = new Socket("127.0.0.1", 8888); PrintWriter pw=new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); pw.write("客户端"+socket.hashCode()+"已连接"); pw.flush(); //获取服务器端响应信息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String info = null; new ClientThread(socket).start(); new ClientThreadR(socket).start(); } catch (Exception e) { e.printStackTrace(); } }}
package CStest;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class ClientThread extends Thread { Socket socket = null; public ClientThread(Socket socket) { this.socket = socket; } public void run() { BufferedReader br = null; String info = null; try { //获取服务器信息 br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (true) { if ((info = br.readLine()) != null) { System.out.println(info); } } } catch (Exception e) { e.printStackTrace(); } }}
package CStest;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.util.Scanner;public class ClientThreadR extends Thread { Socket socket = null; Scanner inp=new Scanner(System.in); public ClientThreadR(Socket socket) { this.socket = socket; } public void run() { // 给服务器发送信息 PrintWriter pw = null; try { pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));// pw.write("客户端"+socket.hashCode()+"已建立连接:\n");// pw.flush(); while(true) { System.out.println("客户端"+socket.hashCode()+":"); pw.write(inp.nextLine()+"\n"); pw.flush(); } } catch (Exception e) { e.printStackTrace(); } }}
package CStest;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.List;public class ServerTest { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(8888); System.out.println("服务器启动\n"); List<Socket> list = new ArrayList<Socket>(); while (true) { Socket socket = server.accept(); list.add(socket); //启动线程 new ServerThreadR(socket,list).start(); System.out.println("已连接Client" + socket.hashCode()+":"); } } catch (Exception e) { e.printStackTrace(); } }}
package CStest;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.util.ArrayList;import java.util.List;public class ServerThreadR extends Thread { Socket socket = null; List<Socket> list = null; public ServerThreadR(Socket socket, List<Socket> list) { this.socket = socket; this.list = list; } PrintWriter pw = null; public void run() { BufferedReader br = null; String info = null; try { // 客户端登录,服务器向客户端发送 pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); pw.write("客户端"+socket.hashCode()+"登录\n"); pw.flush(); while (true) { // 读客户端信息,监听 br = new BufferedReader(new InputStreamReader(socket.getInputStream())); if ((info = br.readLine()) != null) { ServerReader(info); System.out.println("Client" + socket.hashCode() + ": " + info); } } } catch (Exception e) { e.printStackTrace(); } } public void ServerReader(String str) { for (int i = 0; i < this.list.size(); i++) { PrintWriter pw = null; try { pw = new PrintWriter(this.list.get(i).getOutputStream()); pw.write(str + "\n"); pw.flush(); } catch (IOException e) { e.printStackTrace(); } } }}
//粘贴的有点乱,一共五个类,客户端和一个监听一个输入两个线程,服务端和一个监听,你可以试试,不会来交流下,或者粘贴不对的,可以留下邮箱
我也不明白,前面的回答说的是下一节的循环吧,这还没有循环呢
客户端是关闭输出流socket.shutdownOutput();
哪位美丽帅气高端大气的资深大神可以帮忙用图像化界面来实现下面的代码吗?-此致,敬礼!
package com.tomcat;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
public static final String WEB_ROOT=System.getProperty("user.dir") + File.separatorChar + "webRoot";
private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
private boolean shutdown = false;
public static void main(String []args){
HttpServer server = new HttpServer();
server.await();
}
public void await(){
ServerSocket serverSocket = null;
int port = 8080;
try{
serverSocket = new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));
}catch(Exception e){
e.printStackTrace();
System.exit(1);
}
while(!shutdown){
Socket socket = null;
InputStream in = null;
OutputStream out = null;
try {
socket = serverSocket.accept();
in = socket.getInputStream();
out = socket.getOutputStream();
Request request = new Request(in);
request.parse();
Response response = new Response(out);
response.setRequest(request);
response.sendStaticResource();
socket.close();
shutdown = request.getUri().equals("SHUTDOWN_COMMAND");
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
}
----------------------------------------------------------------------------------------------------
package com.tomcat;
import java.io.IOException;
import java.io.InputStream;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input){
this.input = input;
}
public void parse(){
StringBuffer request = new StringBuffer(2048);
int i;
byte [] buffer = new byte[2048];
try{
i = input.read(buffer);
}catch(IOException e){
e.printStackTrace();
i = -1;
}
for(int j=0;j<i;j++){
request.append((char)buffer[j]);
}
System.out.println(request.toString());
uri = parseUri(request.toString());
}
private String parseUri(String requestString){
int index1,index2;
index1 = requestString.indexOf(' ');
if(index1 != -1){
index2 = requestString.indexOf(' ', index1+1);
if(index2 > index1){
return requestString.substring(index1+1,index2);
}
}
return null;
}
public String getUri(){
return uri;
}
}
----------------------------------------------------------------------------
package com.tomcat;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
private static final int BUFFER_SIZE=1024;
Request request;
OutputStream out;
public Response(OutputStream out){
this.out = out;
}
public void setRequest(Request request){
this.request = request;
}
public void sendStaticResource() throws IOException{
byte []bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;
try{
File file = new File(HttpServer.WEB_ROOT,request.getUri());
if(file.exists()){
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE);
while(ch != -1){
out.write(bytes,0,ch);
ch = fis.read(bytes,0,BUFFER_SIZE);
}
}else{
String errorMessage = "HTTP/1.1 404 File Not Found\n" +
"Content-Type:text/html\n" +
"Content-Length:23\n" +
"\n" +
"<h1>File not Found</h1>";
out.write(errorMessage.getBytes());
}
}catch(Exception e){
System.out.println(e.toString());
}finally{
if(fis != null)
fis.close();
}
}
}
不要关闭输入流,去掉客户端的s.shutdownInput试一试
服务端要
//关闭输入流
socket.shutdownInput();
客户端要
//关闭输出流
socket.shutdownOutput();;
最后都只需socket.close();
socket建立的时候是需要ip和端口的,例如你的服务端ip是10.0.0.1,端口是8888,你在其他客户端设置对应的ip以及端口就行Socket socket=new Socket("10.0.0.1", 8888);
// 客户端发送数据
private void sendData(Socket socket, String data) throws IOException {
// 获取输出流,向服务器端发送信息
// 字节输出流
OutputStream oStream = socket.getOutputStream();
PrintWriter pWriter = new PrintWriter(oStream);
// 将输出流包装为打印流
pWriter.write(data);
// 调用flush()方法将缓冲输出
pWriter.flush();
// 关闭输出流
socket.shutdownOutput();
}
// 客户端接收数据
private void receiveData(Socket socket) throws IOException {
// 3.获取输入流,读取服务器的响应信息
InputStream iStream = socket.getInputStream();
// 将输入流转换为字节流,并添加缓冲
InputStreamReader iReader = new InputStreamReader(iStream);
BufferedReader bReader = new BufferedReader(iReader);
String info = null;
// 循环读取服务器端的响应信息
while ((info = bReader.readLine()) != null) {
System.out.println("我是客户端,服务器端说:" + info);
}
}
个人觉得客户端和服务器端在响应完对方的消息之后都应该关闭相应的输入流输出流,所以在Server类和Client类里都要调用一次shutDownInput和shutDownOutput方法,老师没有加响应后的流关闭方法也没出错,大概是因为客户端和服务器端只交互了一次,可能之后再次交互的话就会出错。
服务器要等待客户端的连接 之后再给客户端响应
对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可。
client文件代码中,socket.shutdownInput()这句错误了,应该是socket.shutdownOutput();
错误异常意思是socket被关闭了。按你的代码while(true)死循环里的socket.shutdownOutput();socket.shutdownInput();其实际意思是当前socket的输入和输出已经被关闭,不管服务器输入或客户端输出数据都不行了,因此程序会崩掉。
按照一楼的回答,就是要在while循环里把这两句代码删了就可以;或者我的另一个想法就是把Socket socket = new Socket("127.0.0.1", 8888);这句代码放进while循环中,让它每循环一次都建新的socket对象,但这种做法较耗内存资源。
一个是节点流 一个是处理流 节点流只能处理字节 但是处理流可以处理诸如对象,字符串,压缩文件等等不同的数据,处理起来比节点流要方便
发送完或者接收完之后就关闭这两个流。调用对应的shutdownoutput()和shutdowninput()方法。
一般不需要关闭吧,除非你确定执行到某一步后客户端不再需要与服务器通信,此时关闭socket即可
//1.创建客户端Socket,指定服务器地址和端口
Socket socket = new Socket("localhost", 8888);
//2.获取输出流,向服务器端发送信息
OutputStream os = socket.getOutputStream();//字节输出流
PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
pw.write("用户名:admin;密码:123");
pw.flush();
//3.获取输入流,并读取服务器端的响应信息
socket.shutdownOutput();
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(is));//字节流包装成字符流并添加缓冲
String info = null;
while((info = br.readLine()) != null){
System.out.println("我是客户端,客户端说:"+info);
}
client类中把socket.shutdownInput();写成了这个
估计是shutdownInput和shutdownOutput搞反了