基于Tcp的socket网络传输
服务端与客户端交互
每个软件程序(服务端)都有一个端口及对应的端口号 客户端通过端口号来找到相应软件程序 所以发布程序时需要先绑定端口号 ServerSocket(8888) 客户端通过Socket(ip地址 端口号)访问
accept() (ServerSocket提供)服务端监听是否有客户端访问 返回一个Socket对象
建立起双向链接
服务端向客户端发送信息 OutputStream()(输出流)
客户端接受信息 InpitStream()(输入流)再反馈信息OutputStream()(输出流)
服务端接受信息 InpitStream(输入流)
InpitStream() OutputStream() 都是 通过Socket
最后close() 关闭
注意:数据全放在内存中!
文件传输时 先将文件从硬盘读入到内存中
接受时也是从内存到硬盘
内存->硬盘 out 硬盘->内存 in
服务端
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args) throws IOException {
//绑定服务端口 ip:本机ip
//暴露一个端口 该服务的地址 本机ip:8888
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
System.out.println("与客户端连接成功");
//服务端向客户端发送消息Output
OutputStream out = socket.getOutputStream();
// String info = "hello";
// out.write(info.getBytes());//String->byte 发送
//
//发送文件
//准备要发送的文件
File file = new File("D:\\冯伟清20178461204.zip");
//将此文件 从硬盘读入到内存
InputStream fileIn = new FileInputStream(file);
byte[] fileBytes = new byte[100];
//若文件过大 超过缓冲区 不能一次发送完毕 需要循环来分次发送
int len = -1;//read方法中若返回-1则表明读取完毕
while((len = fileIn.read(fileBytes)) !=-1) {
out.write(fileBytes,0,len);
}
System.out.println("发送成功");
//接受客户端消息
InputStream in = socket.getInputStream();
byte[] bs = new byte[100];//缓冲区
in.read(bs);
System.out.println("接受客户端发来的消息" + new String(bs));
fileIn.close();
out.close();
in.close();
socket.close();
server.close();
}
}
客户端
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//客户端 连接Server发布的服务
Socket socket = new Socket("192.168.1.5",8888);;
//接受服务端发送的信息 Input
InputStream in = socket.getInputStream();
//接受hello
// byte[] bs = new byte[100];
// in.read(bs);//读取到bs内
//byte[]->String
// System.out.println("client接收到的消息:"+new String(bs));
//接受文件
byte[] bt = new byte[100];//接受每分次接收到的信息(100bytes)
int len = -1;
OutputStream fileOut = new FileOutputStream("E:\\9233.zip");
while((len=in.read(bt))!=-1) {
fileOut.write(bt,0,len);
}
System.out.println("下载成功");
//客户端向服务端做出反馈(向服务端发送信息)
OutputStream out = socket.getOutputStream();
out.write("world".getBytes());//转化为字节传输
fileOut.close();
out.close();
in.close();
socket.close();
}
}
多线程并发下载时
Runnable
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class MyDownload implements Runnable{
//处理下载的线程
private Socket socket;
public MyDownload(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
System.out.println("与客户端连接成功");
//服务端向客户端发送消息Output
OutputStream out = socket.getOutputStream();
File file = new File("D:\\text.txt");
//将此文件 从硬盘读入到内存
InputStream fileIn = new FileInputStream(file);
byte[] fileBytes = new byte[100];
//若文件过大 超过缓冲区 不能一次发送完毕 需要循环来分次发送
int len = -1;//read方法中若返回-1则表明读取完毕
while((len = fileIn.read(fileBytes)) !=-1) {
out.write(fileBytes,0,len);
}
System.out.println("发送成功");
fileIn.close();
out.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务端
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9999);
while(true) {
Socket socket = server.accept();//接收请求
//下载的线程
// MyDownload download = new MyDownload(socket);
// //download不可直接start需要先转变成thread
// Thread downloadThread = new Thread(download);
// downloadThread.start();
//优化代码:
new Thread(new MyDownload(socket)).start();
}
}
}
客户端不变