目的
了解并学习网络,达到能在程序中运用网络的目的
知识点
- 网络编程:在两台不同的计算机之间数据传递
- 客户端:与服务器端相对的,为客户提供本地服务的程序,如:手机APP 浏览器 桌面QQ
- 服务器端:存储/处理数据
- URL:统一的资源定位
- 网址表示:当我们打开浏览器随便输入什么,比如:输入android时
它的网址是https://www.so.com/s?q=android&src=srp&fr=360_wsyjsw_recom3.7.1&ls=sn2321298&lm_extend=ctype%3A4&psid=da1039746140ba0878ed253ad4300c1a
他们分别代表:- http/https:传输协议 TCP/IP协议
- www.baidu.com:域名 表示一台网络中的电脑
ipv4 ipv6地址:唯一表示一台网络中的计算机
32位:四个部分 每个部分是8个字节
某台电脑的地址172.20.10.15<->www.baidu.com等价
DNS服务器:域名解析
将www.baidu.com类型的地址解析为对应的ip地址
- search对应的后台程序文件php java jsp
- ?表示运行这个程序需要的参数
- code=android code是服务器端规定的字段
- &如果有多个参数使用&符号链接
- ip地址:表示某一台电脑
- 端口号:用来标识这台电脑上的某一个进程 (80端口)
- 数据传输:TCP/IP协议
- TCP:面向连接的(安全的) 比如:打电话
- UDP:面向无连接的(不安全的,但快) 比如:飞鸽传书
- 网络中的数据传输:Socket实现->套接字
- Socket:客户端
- ServerSocket:服务器端
内容
1.简单实现数据发送
2.手动输入内容发送
3.发送图片
4.实现对聊
5.实现群聊
具体内容
1.简单实现数据发送
//模拟客户端
class Client{
public static void main(String[] args) throws IOException {
//1.创建用于通信的socket
//指明谁通信 ip地址 端口号
Socket socket=new Socket("192.168.43.96",8915);
//接收服务器端的数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//向服务器端发送数据
String line= null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//客户端向服务器端发送数据
PrintStream ps=new PrintStream(socket.getOutputStream());
ps.println("你好啊");
socket.shutdownOutput();
}
}
//模拟服务器端
class Server{
public static void main(String[] args) throws IOException {
//1.创建服务器端的serversocket
ServerSocket ss=new ServerSocket(8915);
//2.获取连接的客户端的socket
Socket clientSocket=ss.accept();
//3.向客户端发送数据
PrintStream ps=new PrintStream(clientSocket.getOutputStream());
ps.println("登录成功");
//输出完毕
clientSocket.shutdownInput();
//4.接收客户端发来的数据
BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
}
}
先运行服务器端再运行客户端
2.手动输入内容发送
- 读取数据:服务器读取 客户端读取
BufferedReader->InputStreamReader->socket.getInputStream()
读取终端
BufferedReader->InputStream->System.in- 输出:客户端输出 服务器输出
BufferedWriter->OutputStream->socket.getOutputStream
PrintStream->socket.Stream()- socket 扮演的是客户端
- ServerSocket扮演的是服务器端
从服务器端输入,将输入的内容发送给客户端
客户端
class MyClient {
public static void main(String[] args) {
//连接客户端的socket
Socket socket=null;
try{
socket=new Socket("192.168.43.96",8662);
//接收服务器端信息
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}catch (IOException e){
System.out.println("网络出错,请重新输入");
}finally {
try{
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
服务器端
class MyServer{
public static void main(String[] args) {
//创建ServerSocket
try(ServerSocket ss=new ServerSocket(8662)) {
//监听客户端的连接
Socket socket=ss.accept();
//从终端接收数据
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
//获取向客户端输出数据的输出流
PrintStream ps=new PrintStream(socket.getOutputStream());
String line=null;
while ((line=keyin.readLine()) !=null){
//发送给客户端
ps.println(line);
}
//发送给客户端
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.发送图片
实现客户端向服务器端发送图片
客户端
class Client{
public static void main(String[] args) throws IOException {
//连接服务器端,获取socket
Socket socket=new Socket("127.0.0.1",8089);
//创建服务器端对应的输入流 用于接收服务器发来的数据
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println(br.readLine());
//向服务器端发送图片(文件)
//1.将文件写入到内存
String path="/Users/Administrator/Desktop/1564315747404.jpeg";
FileInputStream fis=new FileInputStream(path);
//2.创建字节流
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
//3.将文件的内容一点一点的传输给服务器
byte[] buf=new byte[1024];
int len=-1;
while ((len=fis.read(buf))!=-1){
bos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
服务器端
class Server{
public static void main(String[] args) throws IOException {
//创建服务器端的ServerSocket
ServerSocket ss=new ServerSocket(8089);
//监听客户端连接
//当有客户端来连接,服务器一直在这里等待
//当有客户端连接这个服务器,就可以得到对应的server
Socket socket=ss.accept();
//创建客户端对应的输出流,用于向这个客户端发送数据
PrintStream ps=new PrintStream(socket.getOutputStream());
ps.println("连接成功,可以发送数据了");
//接收客户端传递过来的图片
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//文件对应的输出流
String path="/Users/Administrator/AndroidStudioProjects/javaday1/src/main/java/day12/Medica/1.jpeg";
FileOutputStream fos=new FileOutputStream(path);
byte[] buf=new byte[1024];
int len=-1;
while ((len=bis.read(buf))!=-1){
fos.write(buf,0,len);
}
}
}
4.实现对聊
使用多线程实现对聊
- 客户端和服务器端都可以随意的发送内容
- 从终端输入
- 客户端
主线程:接收终端输入 将终端输入发送给服务器端
子线程;接收服务器端发过来的内容- 服务器端
主线程:接收终端输入 将终端输入发送给客户端
子线程:接收客户端发过来的数据
客户端
class Client{
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",8087);
//主线程处理终端输入发送给服务器端
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
PrintStream ps=new PrintStream(socket.getOutputStream());
//用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
- 创建一个子线程处理客户端接收服务器端的数据
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket对象
public ClientThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
//获取服务器端的输入流对象
BufferedReader br= null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络连接错误,请重新输入");
e.printStackTrace();
}finally {
try {
if (br != null) {
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
}
}
}
}
服务器端
class Server{
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(8087);
//接收客户端的socket
Socket socket=ss.accept();
//创建子线程 处理客户端输入数据
new ServerThread(socket).start();
//终端输入流对象
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
//客户端输出流
PrintStream ps=new PrintStream(socket.getOutputStream());
//读取终端输入,将输入输出给客户端
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
创建一个子线程处理服务端接收客户端的数据
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常,请重新登录");
e.printStackTrace();
} finally {
//关闭输入输出流
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
}
}
}
}
5.实现群聊
客户端
class Client{
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",5001);
//主线程处理终端输入发送给服务器端
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
PrintStream ps=new PrintStream(socket.getOutputStream());
//用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket对象
public ClientThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
//获取服务器端的输入流对象
BufferedReader br= null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络连接错误,请重新输入");
e.printStackTrace();
}finally {
try {
if (br != null) {
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
}
}
}
}
服务器端
class Server{
//保存每一个连接过来的对象
public static ArrayList sockets=new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(5001);
//不停的等待客户端来连接数据
while (true) {
Socket socket = ss.accept();
//当有客户端过来了就保存
sockets.add(socket);
//开启一个线程处理客户端的输入
new ServerThread(socket).start();
}
}
}
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
//群发消息
//遍历Server维护的每一个数组
for (Socket s:Server.sockets){
//向socket对应的客户端发送消息
PrintStream ps=new PrintStream(s.getOutputStream());
ps.println(line);
}
}
} catch (IOException e) {
System.out.println("网络异常,请重新登录");
e.printStackTrace();
} finally {
//关闭输入输出流
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
}
}
}
}
小结
慢慢地,我们正在将前面学过的知识运用到不同的场景,实现知识融合,这是很好的将短期记忆转化成长期记忆的方法,不仅仅学习了新知识,还将学过的一并实现。我们一起回想加深对其的理解。我相信,编程这条路虽难,但越难的东西越能激起人的挑战欲,让我进步,我会继续加油的。