TCP协议面向连接,提供可靠传输,使用TCP协议传输文件时需要发送方和接收方先经过三次握手建立可靠连接,发送方一边发接收方一边收,传输完成后双方再通过五次挥手断开连接,如果接受方端口没开将导致报错,但能确保数据都能送到接收方手里
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
//服务器:接收客户机上传的文件,接收完毕后给客户机回信
public class Server {
public static void serverResponse(String filepath) throws IOException {
//建立服务器
ServerSocket server = new ServerSocket(8888);
System.out.println("服务启动");
//监听端口,随时等待客户机连接,当一个客户机连接后,建立一条线程为其服务,随后继续监听端口
while(true){
System.out.println("等待连接......");
Socket client = server.accept();
String name = client.getLocalSocketAddress().toString();
System.out.println("客户机"+name+"进行了连接");
new Thread(new Channel(client, filepath)).start();
}
}
//封装内部类:多线程处理多个客户机的访问
private static class Channel implements Runnable{
String filepath;
InputStream sis;
DataOutputStream sos;
//构造器
private Channel(Socket client, String filepath) {
try {
//利用IO流进行数据传输
sis = new BufferedInputStream(client.getInputStream());
sos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
this.filepath = filepath;
}
//run方法:具体操作
@Override
public void run() {
//具体操作:接收数据
byte[] datas = new byte[1024*10];
int len = 0, i = 1;
File destfile = new File(filepath);
System.out.println("开始接收客户机传来的数据");
while(len != -1) {
try {
len = sis.read(datas);
if(len != -1){
System.out.println("收到第" + i + "个包,大小" + len + "字节");
FileUtils.writeByteArrayToFile(destfile, datas, true);
i++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
//具体操作:给客户机回信
sos.writeUTF("文件已被接收");
System.out.println("STOP");
//释放资源
sis.close();
sos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.*;
import java.net.Socket;
//客户机:向服务器上传文件,并接收服务器的回信
public class Client {
public static void clientRequest(String filepath) throws IOException {
//建立客户机,与服务器建立连接
Socket client = new Socket("localhost", 8888);
System.out.println("已连接服务");
//利用IO流进行数据传输
byte[] flush = new byte[1024*10];
int len, i=1;
InputStream is = new BufferedInputStream(new FileInputStream(filepath));
OutputStream os = new BufferedOutputStream(client.getOutputStream());
while((len = is.read(flush)) != -1){
System.out.println("发送第"+i+"个包");
os.write(flush, 0, len);
os.flush();
i++;
}
//释放Socket的输出流资源,否则在该例子下会导致死锁
//Socket的输出流资源被占用,而服务器需要利用输出流来给客户机回信,故此时服务器会进入阻塞,而客户机又在阻塞状态等待客户机回信,不会继续运行以释放输出流资源
client.shutdownOutput();
//接收服务器回信
DataInputStream dis = new DataInputStream(client.getInputStream());
String result = dis.readUTF();
System.out.println(result);
dis.close();
is.close();
os.close();
client.close();
}
}