JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录
JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录
我们继续网络编程
一.TCP
说完UDP,我们就来说下我们应该重点掌握的TCP了
- TCP传输
- Socket和ServiceSocket
- 建立客户端和服务端
- 建立连接后,通过Socket中的IO流进行数据的传输
- 关闭Socket
同样的,我们的客户端和服务端都是两个独立的应用
我们通过查阅API文档发现,该对象在建立的时候,就可以去连接指定主机,因为tcp是面向连接的,所以在建立socket服务时,就要有服务存在,并成功连接,形成通路后,在该通道进行数据传输
所以我们用代码来看下他的步骤
客户端
package com.lgl.hellojava;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient {
public static void main(String[] args) {
try {
//1.创建客户端的服务,传地址和端口
Socket s = new Socket("192.168.1.102",10000);
//2.为了发送数据,应该获得socket流中的输出流
OutputStream out = s.getOutputStream();
out.write("你好".getBytes());
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务端
package com.lgl.hellojava;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 定义端点接收数据打印出来
* 服务端:
* 1.建立服务端的socket服务,servicesocket,并监听一个端口
* 2.获取连接过来的客户端对象,通过accept方法,这个方法是阻塞的,没有连接就会等
* 3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该对象的读取流
* 4.关闭服务端(可选操作)
* @author LGL
*
*/
public class TcpService {
public static void main(String[] args) {
try {
//1.建立连接,监听端口
ServerSocket ss = new ServerSocket(10000);
//2.连接客户端对象
Socket accept = ss.accept();
//获取ip
String ip = accept.getInetAddress().getHostAddress();
//3.获取客户端发送过来的数据
InputStream in = accept.getInputStream();
//4.开始读取
byte [] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
//5.关闭
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
二.TCP互相传输
我们在来写一个实例去说明,他们的互访动作,这里为了写起来方便,就写在一个类中了
package com.lgl.hellojava;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端发送信息,服务端收到,反馈信息
*
* @author LGL
*
*/
public class Tcp {
public static void main(String[] args) {
try {
Socket s = new Socket("192.168.1.102", 10005);
OutputStream out = s.getOutputStream();
out.write("我是客户端".getBytes());
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf, 0, len));
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 服务端
* @author LGL
*
*/
class Server {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(10005);
Socket s = ss.accept();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf, 0, len));
OutputStream out = s.getOutputStream();
out.write("收到后反馈".getBytes());
s.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
三.复制文件
同样的这里也是使用的流,我们具体来看下怎么去操作,我们同样的,写在一个类中
package com.lgl.socket;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class FileClient {
public static void main(String[] args) {
try {
Socket s = new Socket("192.168.1.102", 10006);
BufferedReader bufr = new BufferedReader(new FileReader("test.txt"));
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
String line = null;
while ((line = bufr.readLine()) != null) {
pw.println(line);
}
pw.print("over");
BufferedReader bufIn = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String str = bufIn.readLine();
System.out.println(str);
bufr.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class FileServer {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(10006);
Socket s = ss.accept();
BufferedReader bufIn = new BufferedReader(new InputStreamReader(
s.getInputStream()));
PrintWriter out = new PrintWriter(new FileWriter("test1.txt"), true);
String line = null;
while ((line = bufIn.readLine()) != null) {
if ("over".equals(line))
break;
out.println(line);
}
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
pw.println("上传成功");
out.close();
s.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
四.上传图片
我们再来看下图片是怎么上传的,我们先来分析下步骤
客户端
- 1.服务端点
- 2.读取客户端已有的图片数据
- 3.通过socket,发送给服务端
- 4.读取服务端反馈的信息
- 5.关闭资源
**
* 客户端
*
* @author LGL
*
*/
public class PicClient {
public static void main(String[] args) {
try {
Socket s = new Socket("192.168.1.102", 10009);
FileInputStream fis = new FileInputStream("1.png");
OutputStream out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
out.write(buf, 0, len);
}
//告訴服务端数据写完
s.shutdownInput();
InputStream in = s.getInputStream();
byte[] bufn = new byte[1024];
int num = in.read(bufn);
System.out.println(new String(bufn, 0, num));
fis.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务端
直接看代码
/**
* 服務端
* @author LGL
*
*/
class PicServer {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(10009);
Socket s = ss.accept();
InputStream in = s.getInputStream();
FileOutputStream fos = new FileOutputStream("2.png");
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) != -1) {
fos.write(buf, 0, len);
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
fos.close();
s.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
其实跟I/O区别真不大,但是概念一定要了解清楚
五.多并发上传
多并发这个概念就是多人互动了,这对服务器的负荷还是有考究的,这里呢,我们就模拟一下,多人上传图片的场景,我们是怎么做的?我们还是在上传图片的那份代码上更改
首先我们可以确定的是,这是服务端的代码
- 这个服务端有个局限性,当A客户端连接之后,被服务端获取到,服务端就在执行代码了,这个时候如果B客户端连接只有等待,这就是我们需要多并发的原因了,为了让多个客户端同时连接,服务端最好就是讲每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端请求
如何定义线程?
- 只要明确了每个客户端要在服务端执行的代码即可
/**
* 服務端
*
* @author LGL
*
*/
class PicServer {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(10009);
while (true) {
Socket s = ss.accept();
new Thread(new PicThread(s)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 并发线程
* @author LGL
*
*/
class PicThread implements Runnable {
private Socket s;
public PicThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
String ip = s.getInetAddress().getHostAddress();
System.out.println("ip:" + ip);
long millis = System.currentTimeMillis();
File file = new File(millis + ".png");
InputStream in = s.getInputStream();
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) != -1) {
fos.write(buf, 0, len);
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
fos.close();
s.close();
} catch (Exception e) {
throw new RuntimeException("上传失败");
}
}
}
其实我写的代码还是有点烂的,但是思想在就好,我们得先把思想学会了
六.多并发登录
上面说的多并发的上传,实在服务端端,现在我们来说下登录,是作用在客户端
package com.lgl.socket;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class LoginClient {
public static void main(String[] args) {
try {
Socket s = new Socket("192.168.1.102", 10008);
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
BufferedReader bufIn = new BufferedReader(new InputStreamReader(
s.getInputStream()));
for (int i = 0; i < 3; i++) {
String line = bufr.readLine();
if (line == null) {
break;
}
out.println(line);
String info = bufIn.readLine();
System.out.println("info:" + info);
if (info.contains("欢迎")) {
break;
}
}
bufr.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 服务端
*
* @author LGL
*
*/
class LoginServer {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(10008);
while (true) {
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 并发登陆
*
* @author LGL
*
*/
class UserThread implements Runnable {
private Socket s;
public UserThread(Socket s) {
this.s = s;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
try {
BufferedReader bufrIn = new BufferedReader(
new InputStreamReader(s.getInputStream()));
String name = bufrIn.readLine();
// 模拟读取数据库的用户名
BufferedReader bufr = new BufferedReader(new FileReader(
"user.txt"));
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
String line = null;
boolean flag = false;
while ((line = bufr.readLine()) != null) {
if (line.equals(name)) {
flag = true;
break;
}
}
if (flag) {
System.out.println("已登录");
out.print("欢迎");
} else {
System.out.println("重新登录");
out.println("用户名不存在");
}
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
OK,这些代码中可能会存在一些错误,因为代码并没有去实际的验证中,我写的时候也是跟着思想去走的,这样写代码是极为友好的,这就是TCP的冰山一角了,不过关于这些,还有很多知识点,我们要做的就是把思想给掌握了,万变不理其中
好的,最近写文的时间,有点懈怠了,看来要发力了,嘻嘻,
有兴趣的加群:555974449 一起来玩玩吧!
JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录的更多相关文章
- JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this
JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...
- “全栈2019”Java多线程第三十三章:await与signal/signalAll
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java从零开始学三十三(JAVA IO- File类)
一.简述 在整个io包中,唯一表示与文件本身有关的类就是File类.使用File类可以进行创建或删除文件等常用操作.要想使用File类,则首先要观察File类的构造方法,此类的常用构造方法如下所示: ...
- Java网络编程三--基于TCP协议的网络编程
ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状体 Socket accept():如果接收到客户端的连接请求,该方法返回一个与客户端对应Socket ...
- 菜鸡的Java笔记 第三十三 - java 泛型
泛型 GenericParadigm 1.泛型的产生动机 2.泛型的使用以及通配符 3.泛型方法的使用 JDK1.5 后的三大主 ...
- JAVA学习第三十三课(经常使用对象API) —迭代器
数字有非常多用数组存,对象有非常多就要用集合存 可是数组是固定长度的,集合是可变长度的 集合的由来: 对象用来封装特有数据,对象多了须要存储,假设对象个数不确定,就须要使用集合容器来存储 集合的特点: ...
- Java基础(三十三)JDBC(3)操作数据库
一.添加数据 在SQL语句中,一条INSERT语句只能添加一条记录,因此分为几种情况进行添加数据操作. 1.添加一条记录 (1)如果只需要添加一条记录,通常情况下通过Statament实例完成. tr ...
- java 面向对象(三十三):泛型二 泛型在集合中的使用
1. 在集合中使用泛型之前的例子 @Test public void test1(){ ArrayList list = new ArrayList(); //需求:存放学生的成绩 list.add( ...
- Java开发学习(三十三)----Maven私服(一)私服简介安装与私服分类
一.私服简介 团队开发现状分析 (1)张三负责ssm_crm的开发,自己写了一个ssm_pojo模块,要想使用直接将ssm_pojo安装到本地仓库即可 (2)李四负责ssm_order的开发,需要用到 ...
- (三十三)Xcode项目的重要工程文件
1.Supporting files内有一个Xxx-Info.plist文件(旧版本Xcode的配置文件叫Info.plist).因此自定义的plist不要带Info关键词. 这个plist是系统的全 ...
随机推荐
- 成也DP,败也DP(AFO?)
不知道想说什么.. 从来没写过博客,markdown什么的也不会,凑合着看一下吧. 初中的时候开始搞OI,学了两个月后普及组爆零就退赛了. 初三直升的时候说每个人都要选竞赛,抱着混一混的心态选了信息, ...
- hdu 3247 AC自动+状压dp+bfs处理
Resource Archiver Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Ot ...
- hdu3966 点权模板-树链部分
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 开发者说 | 使用Visual Studio Code编译、调试Apollo项目
转载地址:https://mp.weixin.qq.com/s?__biz=MzI1NjkxOTMyNQ==&mid=2247484266&idx=1&sn=d6bcd4842 ...
- mvn package 和 mvn install
刚刚准备将maven项目中一个子项目打个包,使用了mvn package.心想这个很简单嘛,没料就报错了.报错咱不怕,看看错在哪就好了. 编译出错,找不到我定义的异常类中的配置.那应该是引用父模块出来 ...
- React .js框架的环境搭建
React学习笔记(一)- 环境搭建 最近在学习react相关的知识,刚刚起步,一路遇坑不断.自己做个笔记,方便日后总结,也供相同趣味的小伙伴一起交流探讨. 学习时主要参考官网的教程:https: ...
- 使用pscp实现Windows 和 Linux 服务器间的远程拷贝文件
在工作中,每次部署应用时都需要从本机Windows 服务器拷贝文件到Linux 上,有时还将Linux 上的文件拷到本机,这些操作都是可以使用pscp实现的.下文将详细描述如何使用: PSCP (Pu ...
- linux安装mysql数据库
安装mysql 1.下载MySQL的安装文件 安装MySQL需要下面两个文件: MySQL-server-4.0.23-0.i386.rpm MySQL-client-4.0.23-0.i386.rp ...
- Mysql 获取表的comment 字段
查看获取表内字段注释: > show full columns from tablename; 或是 show full fields from tablename; 或是,在元数据的表里面看 ...
- 关于npm run build 报错解决方案
# 特定的错误 ERROR in statics/mobile/js/vendor.cef13a0e680a5bc0d8b3.js from UglifyJsUnexpected token: pun ...