一.TCP的客户端和服务器
TCP通信同UDP一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。区别在于,UDP中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意的发送数据。而TCP通信时严格区分客户端和服务器端的,在通信时,必须先由客户端去链接服务器端才能实现通信,服务器端不可以主动链接客户端,并且服务器端程序必须事先启动,等待客户端的链接。在jdk中提供了两个类用于实现TCP程序,一个时ServerScoket类,用于表示服务器端,一个是Socket类,用于表示客户端。通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Sokcet对象向服务器端发出链接请求,服务器端响应请求,两者建立链接开始通信。
二.文件上传案例实现
案例分析:
客户端:
1.首先创建客户端对象 调用构造方法传递要连接服务器的ip地址和端口号
2.调用客户端对象的方法getOutputStream() 得到要传输给服务器端的流对象(注意不要自己创建流对象 客户端和服务器端在链接的过程中已经自己创建了流 )
3.创建本地流对象读取本地图片信息 然后通过getOutputStream()方法得到的流对象读取本地数据发送给服务器端
4.调用关闭套接字输出流的方法shutdownOutput(),(为什么要调用shutdownOutput方法的原因:由于服务器端的读取客户端数据的read方法一直在等待客户端的数据传送 导致read一直在等待,(为什么read会一直在等待? api文档给出read功能的解释:因为read功能在读取的时候 如果没有字节可用,因为已经达到流的末尾,则返回值-1。该方法阻塞直到输入数据可用,检测到留的结尾,或抛出异常。 也就是说因为服务器端在读取客户端的流数据一直没有结束,)出现了服务器端程序和客户端程序不结束的情况(线程等待),为了解决这个情况,需要通过关闭客户端套接字的输出流来实现服务器端读取功能的结束。)
5.创建接受服务器返回信息的流对象
6.关闭资源
服务器端:
1.创建接受客户端套接字的对象 传递端口值
2.调用accpet()方法 接受客户端的sokcet对象
3.通过客户端的socket对象 获取客户端的输入流 接受客户端传来的数据
4.通过客户端的输入流 来获取流中的数据
5.关闭资源
1.客户端
public class Cilent {
public static void main(String[] args) throws IOException {
// 创建客户端对象 传递要连接的ip地址和端口号
Socket socket = new Socket("127.0.0.1",6000);
// 创建输出给服务器的流对象
OutputStream out = socket.getOutputStream();
// 创建读取本地图片的流对象
FileInputStream fis = new FileInputStream("g:\\000.jpg");
int len = 0;
byte[] bytes = new byte[1024];
while ((len=fis.read(bytes))!=-1){
out.write(bytes,0,len);
}
// 创建关闭等待
socket.shutdownOutput();
// 创建接受服务器的信息流对象
InputStream in = socket.getInputStream();
len = in.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();;
fis.close();
}
}
2.服务器端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6000);
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
// 创建存放文件夹和对象
File upload = new File("i:\\upload");
if(!upload.exists()){
upload.mkdirs();
}
// 防止文件同名被覆盖
String filename = "qianhe"+System.currentTimeMillis()+new Random().nextInt(99999)+".jpg";
FileOutputStream fos = new FileOutputStream(upload+File.separator+filename);
byte[] bytes = new byte[1024];
int len = 0;
while ((len=in.read(bytes))!=-1){
fos.write(bytes,0,len);
}
socket.getOutputStream().write("上传成功!".getBytes());
socket.close();
serverSocket.close();
fos.close();
}
}
总结:
在实现TCP上传数据的时候,需要先开启服务器端进行等待客户端来传送数据;需要用两套io流对象来实现数据的传输和数据的接受,要搞清楚io流传输的顺序,从客户端传输数据时outputStream ,从服务器端返回数据用的时inputStream。