TCP
1. 发送文本 走IO字符流
2. 发送多媒体文件(图片,音频等) 走IO字节流
发现问题
1 发送文本时
客户端使用BufferedReader读取源数据 ,使用PrintWriter发送数据.
服务器端使用BufferedReader接收数据,使用使用PrintWriter存储数据.
客户端发送数据结束后,如果没有结束标记, 服务器会一直readLine(),因为没有结束标志,导致阻塞.
发送数据结束后,调用Socket.shutDownOutput()方法关闭输出流, 通知服务器已发送完毕.
2. 发送多媒体文件时
客户端使用BufferedInputStream读取源数据,使用BufferedOutputStream发送数据
服务器端使用BufferedInputStream接收数据,使用BufferedOutputStream存储数据
客户端发送数据结束后,如果没有结束标记, 服务器会一直read(),因为没有结束标志,导致阻塞.
发送数据结束后,调用Socket.shutDownOutput()方法关闭输出流, 通知服务器已发送完毕.
3.shutDownOutput() / shutDownInput() 和 Socket.close() 方法的区别
当调用Socket.shutdownInput( )后,禁用这个套接字的输入流, 还能够往该套接字中写数据(执行OutputStream.write( ));
当调用Socket.shutdownOutput( )后,禁用这个套接字的输出流, 还能够往该套接字中读数据(执行InputStream.read( ));
close方法会关闭与服务器的连接
如果在客户端发送完数据直接close的话,服务器端可以接收到客户端发送的数据,但是客户端收不到服务器端发送的回执信息, 并且客户端会抛出SocketException: Socket closed
package com.EndClient;
import java.io.*;
import java.net.Socket;
public class Client_reader {
public static void main(String[] args) {
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
try {
s=new Socket("localhost",9090);
OutputStream os = s.getOutputStream();
pw=new PrintWriter(os,true);
for (int i = 0; i < 3; i++) {
pw.println("haha");
//pw.flush();
}
s.close();
//s.shutdownOutput();
InputStream is = s.getInputStream();
br=new BufferedReader(new InputStreamReader(is));
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
//System.out.println(123); ???
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
如果在客户端最后close的话,服务器端可以收到数据, 并且一直阻塞在readline方法中, 导致循环不退出,客户端收不到回执信息 .一直阻塞,一直等待
package com.EndClient;
import java.io.*;
import java.net.Socket;
public class Client_reader {
public static void main(String[] args) {
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
try {
s=new Socket("localhost",9090);
OutputStream os = s.getOutputStream();
pw=new PrintWriter(os,true);
for (int i = 0; i < 3; i++) {
pw.println("haha");
//pw.flush();
}
//s.close();
//s.shutdownOutput();
InputStream is = s.getInputStream();
br=new BufferedReader(new InputStreamReader(is));
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
//System.out.println(123); ???
s.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端调用shutdown方法时,不会影响与服务器端的连接和服务器端的输入输出.
测试shutDownOutput() / shutDownInput()代码
package com.EndServer;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_reader {
public static void main(String[] args) {
ServerSocket ss=null;
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
try {
ss=new ServerSocket(9090);
s=ss.accept();
InputStream is = s.getInputStream();
br=new BufferedReader(new InputStreamReader(is));
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
System.out.println("isBound: "+s.isBound());
System.out.println("isConnected: "+s.isConnected());
System.out.println("isClosed: "+s.isClosed());
System.out.println("isInputShutdown: "+s.isInputShutdown());
System.out.println("isOutputShutdown: "+s.isOutputShutdown());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.test;
import java.io.*;
import java.net.Socket;
public class Client_reader {
public static void main(String[] args) {
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
try {
s=new Socket("localhost",9090);
OutputStream os = s.getOutputStream();
pw=new PrintWriter(os,true);
for (int i = 0; i < 3; i++) {
pw.println("haha");
}
s.shutdownOutput();
System.out.println("isBound: "+s.isBound());
System.out.println("isConnected: "+s.isConnected());
System.out.println("isClosed: "+s.isClosed());
System.out.println("isInputShutdown: "+s.isInputShutdown());
System.out.println("isOutputShutdown: "+s.isOutputShutdown());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果
实现代码
字符流服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_reader {
public static void main(String[] args) {
ServerSocket ss=null;
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
try {
ss=new ServerSocket(9090);
s=ss.accept();
InputStream is = s.getInputStream();
br=new BufferedReader(new InputStreamReader(is));
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
OutputStream os = s.getOutputStream();
pw=new PrintWriter(os,true);
for(int i=0;i<3;i++){
pw.println("heihei");
//pw.flush();
}
//s.shutdownOutput(); ???
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流客户端
import java.io.*;
import java.net.Socket;
public class Client_reader {
public static void main(String[] args) {
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
try {
s=new Socket("localhost",9090);
OutputStream os = s.getOutputStream();
pw=new PrintWriter(os,true);
for (int i = 0; i < 3; i++) {
pw.println("haha");
//pw.flush();
}
s.shutdownOutput();
InputStream is = s.getInputStream();
br=new BufferedReader(new InputStreamReader(is));
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
//System.out.println(123); ???
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节流服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_stream {
public static void main(String[] args) {
ServerSocket ss=null;
Socket s=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
ss=new ServerSocket(9898);
s=ss.accept();
InputStream is = s.getInputStream();
bis=new BufferedInputStream(is);
bos=new BufferedOutputStream(new FileOutputStream("E:\\b.png"));
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
OutputStream os = s.getOutputStream();
os.write("接收完毕".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节流客户端
import java.io.*;
import java.net.Socket;
public class Client_stream {
public static void main(String[] args) {
Socket s=null;
BufferedOutputStream bos=null;
BufferedInputStream bis=null;
try {
s=new Socket("localhost",9898);
OutputStream os = s.getOutputStream();
bos=new BufferedOutputStream(os);
bis=new BufferedInputStream(new FileInputStream("E:\\01_并行和并发的区别.png"));
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
s.shutdownOutput(); //???
bis=new BufferedInputStream(s.getInputStream());
byte[] bytess=new byte[1024];
int lenn;
while((lenn=bis.read(bytess))!=-1){
System.out.println(new String(bytess,0,lenn));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(s!=null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}