TCP传输
TCP传输是怎样建立的呢?
- Socket和ServerSocket
- 建立客户端和服务器端
- 建立连接后,通过Socket中的IO流进行数据的传输
- 关闭socket
TCP传输客户端与服务器端同样是两个独立的应用程序。
我们就来写一个TCP输出数据的程序。
TCP传输-客户端
/*
* TCP协议发送数据:
* A:创建发送端的Socket对象
* 这一步如果成功,就说明连接已经建立成功了。
* B:获取输出流,写数据
* C:释放资源
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建发送端的Socket对象
Socket s = new Socket("192.168.2.102", 8888);
// 获取输出流,写数据
OutputStream os = s.getOutputStream();
os.write("TCP来了".getBytes());
// 释放资源
s.close();
}
}
TCP传输-服务器
/*
* TCP协议接收数据:
* A:创建接收端的Socket对象
* B:监听客户端连接。返回一个对应的Socket对象
* C:获取输入流,读取数据显示在控制台
* D:释放资源 */
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建接收端的Socket对象
ServerSocket ss = new ServerSocket(8888);
// 监听客户端连接。返回一个对应的Socket对象
Socket s = ss.accept(); // 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
// 获取输入流,读取数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
// 阻塞式方法
String str = new String(bys, 0, len);
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "---" + str);
// 释放资源
s.close();
// ss.close(); //服务器一般不应该关闭
}
}
这样我们九建立了TCP协议传输数据的客户端和服务器,运行程序,服务器会收到客户端发来的数据,但是这样的代码,当服务器端收到客户端的数据时,客户端并不知道,所以,我们就要给客户端一个反馈了。
/* * 服务器端 */
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(11111);
// 监听客户端的连接
Socket s = ss.accept(); // 阻塞
// 获取输入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys); // 阻塞
String server = new String(bys, 0, len);
System.out.println("server:" + server);
// 获取输出流
OutputStream os = s.getOutputStream(); o
s.write("数据已经收到".getBytes());
// 释放资源
s.close();
// ss.close();
}
}
/* * 客户端 */
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.2.102",11111);
// 获取输出流
OutputStream os = s.getOutputStream();
os.write("双十一快乐!".getBytes());
// 获取输入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);// 阻塞
String client = new String(bys, 0, len);
System.out.println("client:" + client);
// 释放资源
s.close();
}
}
上传文件
我们来完成通过TCP协议从客户端上传一个文件到服务器,并给出客户端反馈文件上传成功
/* * 上传文件客户端 */
public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.2.102", 12345);
// 封装文本文件
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封装通道内流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
// 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
//Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了
s.shutdownOutput();
// 接收反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader( s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client);
// 释放资源
br.close();
s.close();
}
}
/* * 上传文件接收端(服务器) */
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建服务器端的Socket对象
ServerSocket ss = new ServerSocket(12345);
// 监听客户端连接
Socket s = ss.accept();// 阻塞
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader( s.getInputStream()));
// 封装文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); String line = null;
while ((line = br.readLine()) != null) {
// 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
// 给出反馈
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter( s.getOutputStream()));
bwServer.write("文件上传成功");
bwServer.newLine();
bwServer.flush();
// 释放资源
bw.close();
s.close();
}
}
这是上传文件并给出反馈的例子,我们再来看上传图片并给出反馈的例子怎么写
上传图片
上传图片我们就要考虑不能用字符流了,要用字节流。
/* * 上传图片客户端 */
public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.2.102", 96320);
// 封装图片文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg"));
// 封装通道内的流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
s.shutdownOutput(); // 读取反馈
InputStream is = s.getInputStream();
byte[] bys2 = new byte[1024];
int len2 = is.read(bys2);
String client = new String(bys2, 0, len2);
System.out.println(client);
// 释放资源
bis.close(); s.close();
}
}
/* * 上传图片接收端-服务器 */
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(96320);
// 监听客户端连接
Socket s = ss.accept();
// 封装通道内流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
// 封装图片文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg"));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
// 给一个反馈
OutputStream os = s.getOutputStream();
os.write("图片上传成功".getBytes());
bos.close();
s.close();
}
}
运行程序,我们将客户端a.jpg的图片上传到服务器后,服务器收到后会给我们返回图片上传成功
多并发上传
在我们平时遇到的情况肯定不是一个客户端对应一个服务器,肯定是多个客户端对应一个服务器,那么就存在了多并发上传,再大型项目中也要考虑服务器的负荷问题,那么我们就来用代码实现一下当多个用户上传文件到服务器时,我们应该怎样做?
如果我们还按照上面上传文件的思路,去进行多并发上传,当一个客户端A建立连接之后,被服务端获取到,服务端就在执行代码了,这个时候如果客户端B建立连接只有等待客户端A操作完成后它才能开始执行,所以为了让多个客户端同时连接到服务器上传代码,我们就要运用多线程技术,把每个客户端和服务器之间的连接封装到一个线程中去,这样就可以同时处理多个客户端请求
/* * 服务器端 */
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(11111);
while (true) {
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
/* * 并发的线程 */
public class UserThread implements Runnable {
private Socket s;
public UserThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader( s.getInputStream()));
// 为了防止名称冲突,每次命名为随机的
String newName = System.currentTimeMillis() + ".java"; BufferedWriter bw = new BufferedWriter(new FileWriter(newName)); String line = null;
while ((line = br.readLine()) != null) {
// 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
// 给出反馈
BufferedWriter bwServer = new BufferedWriter( new OutputStreamWriter(s.getOutputStream()));
bwServer.write("文件上传成功");
bwServer.newLine();
bwServer.flush();
// 释放资源
bw.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样就完成了多用户上传文件到客户端了。