0.前言
今天我们主要讲解一些网络基本概念
这篇文章内容可能有点水,某些原因导致头昏脑胀,已经好几次差点昏过去了,但是还是得坚持写完,请大家多多谅解
若想要了解“类”等其他主要知识,可以去看前面的文章
由于最终目的是要开发安卓app,
因此这里使用的IDE是AS(Android Studio)
(不会使用的可以参考下面这篇文章中的例子)
《[Java]开发安卓,你得掌握的Java知识2》
1.文章主要内容
-
网络的基本概念简单讲解
-
用AS完成简单的服务器端与客户端的交互
2.基础知识讲解
客户端与服务器.png网络相关概念简介
URL:
统一的资源定位,用于找服务器中的某个资源http/https:
超文本传输协议(HyperText Transfer Protocol)
一种传输时候需要遵循的协议TCP/IP协议
它是传输层协议,主要解决数据如何在网络中传输,
而HTTP是应用层协议,主要解决如何包装数据。DNS服务器:
域名解析,将"www.baidu.com"类型的域名解析为对应的ip地址ip地址
某台电脑的ip地址,能找到这台网络中该电脑的位置端口号:
端口号就是用来标识这台电脑上的某个进程
比如QQ的端口号为1
依靠电脑的ip地址和端口号1,就可以访问这台电脑的QQ
- 套接字(socket)
是一个抽象层,应用程序可以通过它发送或接收数据
客户端用的是Socket类,而服务器端用的是ServerSocket类
客户端方面:
Socket类的方法 | 具体描述 |
---|---|
getInputStream | 得到一个输入流,即得到从服务器端发回的数据。 |
getOutputStream | 得到一个输出流,即得到发送给服务器端的数据。 |
服务器端端方面:
Socket类的方法 | 具体描述 |
---|---|
getInputStream | 得到从客户端发送给服务器端的数据流。 |
getOutputStream | 得到发送给客户端的数据。 |
3.服务器端与客户端的简单交互
第一步
在MyClient中创建一个主函数,并且在主函数中创建客户端Socket类对象
构造方法中,第一个参数是欲访问的ip地址,第二个参数是欲访问的端口
public class MyClient{
public static void main(String[] args){
Socket socket = new Socket("127.0.0.1",9090);
}
}
第二步
在MyServer中创建一个主函数,并且在主函数中创建客户端ServerSocket类对象
构造方法中,参数是服务器端开放的端口
public class MyServer{
public static void main(String[] args){
ServerSocket ss = new ServerSocket(9090);
Socket socket = ss.accept();
}
}
第三步
写一个MessageManager类,里面写两个函数:
getTerminalMessageAndSent(Socket socket)
和
getMessageFromOppsite(Socket socket)
public void getTerminalMessageAndSent(Socket socket) throws IOException {
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
String line = null;
PrintStream ps = new PrintStream(socket.getOutputStream());
while ((line = keyIn.readLine()) != null) {
ps.println(line);
}
ps.close();
keyIn.close();
}
- 注意:
(1)BufferedReader的构造方法中需要一个Reader,因此,使用new InputStreamReader()将字节流转成字符流
(2)这个函数主要功能是:获得终端输入的信息并且输出给对面
(3)PrintStream的作用就是通过print()或者println()将内容输出给对方
(4)line = keyIn.readLine()意思是将终端输入的内容赋值给line,然后用ps.println输出
(5)socket.getOutputStream()表示得到想要发送出去的数据
public void getMessageFromOppsite(Socket socket){
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
- 注意:
(1)BufferedReader是用来接收传过来的信息的,所以后面用的是socket.getInputStream(),即获得传入的数据
(2)new InputStreamReader可以将InputStream转换为Reader,以此来初始化BufferedReader
(3)line = br.readLine(),可以将读到的内容赋值给line,然后使用System.out.println()输出
(4)可以使用readLine()的理由是:上面第一个函数中用的是println()
第四步
创建一个Client类,里面写一个静态的socket
public Client{
public static Socket socket;
static {
try {
socket = new Socket("127.0.0.1",9090);
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建一个,Server类,同上
public class Server {
public static ServerSocket serverSocket;
public static Socket socket;
static {
try {
serverSocket = new ServerSocket(9090);
socket = serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
第五步
为Client写两个类,这两个类实现了Runnable接口,即可以放在不同的线程中,以此实现服务端与客户端的实时交互
public class ClientGet implements Runnable{
@Override
public void run() {
MessageManager.instance.getMessageFromOppsite(Client.socket);
ClientManager.countNow++;
//super.run();
}
}
public class ClientSent implements Runnable{
@Override
public void run() {
try {
MessageManager.instance.getTerminalMessageAndSent(Client.socket);
ClientManager.countNow++;
} catch (IOException e) {
e.printStackTrace();
}
}
}
为Server类同理
public class ServerGet implements Runnable{
@Override
public void run() {
try {
MessageManager.instance.getMessageFromOppsite(Server.socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ServerSent implements Runnable{
@Override
public void run() {
try {
MessageManager.instance.getMessageFromOppsite(Server.socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
第六步
在MyClient中实现两个子线程,MyServer中同理
public class MyClient {
public static void main(String[] args) {
ClientGet cg = new ClientGet();
ClientSent ct = new ClientSent();
Thread t = new Thread(cg);
Thread t2 = new Thread(ct);
t.start();
t2.start();
}
}
public class MyServer {
public static void main(String[] args) {
ServerGet sg = new ServerGet();
ServerSent ss = new ServerSent();
Thread t = new Thread(sg);
Thread t2 = new Thread(ss);
t.start();
t2.start();
}
}
最后
先开启MyServer中的main函数,再开启MyClient的,然后,就可以在终端进行交互了,在MyServer的终端输入的内容,可以在MyClient中看到,反之亦然。
4.总结
(1)本文讲解一些网络的简单概念,以及服务器端和客户端的交互相关知识
(2)其实服务器端和客户端交互的基础逻辑概念并不难理解,关键还是在于各种输入流和输出流的运用,必须搞清楚什么时候该用哪种流
(3)只有多练习,才能熟练整个交互过程,为日后安卓开发打下良好的基础
网友评论