IT十八掌Java基础 网络编程

网络编程

计算机网络

是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

网络编程

就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

A:有人说,20世纪最伟大的发明不是计算机,而是计算机网络。

还有人说,如果你买了计算机而没有联网,就等于买了电话机而没有接电话线一样。

网络模型

计算机网络之间以何种规则进行通信,就是网络模型研究问题。

网络模型一般是指

OSI(Open System Interconnection开放系统互连)参考模型

TCP/IP参考模型

网络参考模型图

网络模型7层概述:

1.物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。

2. 数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。

3. 网络层:主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。

4. 传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。

5.会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)

6.表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。

7.应用层: 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。

 

网络编程三要素:

IP地址:InetAddress

网络中设备的标识,不易记忆,可用主机名

端口号

用于标识进程的逻辑地址,不同进程的标识

传输协议

通讯的规则

常见协议:TCP,UDP

A:网络模型说完了,我们要进行通讯,需要哪些要素呢?

比如说:我要跟你说话.

第一个条件:我要先找到你 (IP)

第二个条件:你得有接收数据的地方  耳朵 (端口)

第三个条件:我跟你说话,你能接收到,咱按什么方式接收啊,我说英文你懂吗,说韩文你懂吗,不懂是吧,所以我还是说中文把.(协议)

举例:

我想和XXX说话了。肿么办?

A:我要找到XXX。

B:对她说话,要对耳朵说。

C:我说什么呢?"I Love You"

但是,她没学过英语,听不懂。

我没必要说英语,说汉语就可以了:我爱你

IP地址

要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。

A:所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节。例如一个采用二进制形式的IP地址是“00001010000000000000000000000001”,这么长的地址,人们处理起来也太费劲了。为了方便人们的使用,IP地址经常被写成十进制的形式,中间使用符号“.”分开不同的字节。于是,上面的IP地址可以表示为“10.0.0.1”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多。

B:IP地址的组成

IP地址 = 网络号码+主机地址

A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码

B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码

C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码

特殊地址:

127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1

DOS命令 ipconfig:查看本机IP地址

xxx.xxx.xxx.0 网络地址

xxx.xxx.xxx.255 广播地址

1- 127   256*256*256

A类1.0.0.0---127.255.255.255(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)(2)127.X.X.X是保留地址,用做循环测试用的。

B类128.0.0.1---191.255.255.254172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。256

C类192.0.0.1---223.255.255.254192.168.X.X是私有地址

D类224.0.0.1---239.255.255.254

E类240.0.0.1---247.255.255.254

IP总结

IP地址:

网络中计算机的唯一标识。

计算机只能识别二进制的数据,所以我们的IP地址应该是一个二进制的数据。

但是呢,我们配置的IP地址确不是二进制的,为什么呢?

IP:192.168.1.100

换算:11000000 10101000 00000001 01100100

假如真是:11000000 10101000 00000001 01100100的话。

我们如果每次再上课的时候要配置该IP地址,记忆起来就比较的麻烦。

所以,为了方便表示IP地址,我们就把IP地址的每一个字节上的数据换算成十进制,然后用.分开来表示:

"点分十进制"

IP地址的组成:网络号段+主机号段

A类:第一号段为网络号段+后三段的主机号段

一个网络号:256*256*256 = 16777216

B类:前二号段为网络号段+后二段的主机号段

一个网络号:256*256 = 65536

C类:前三号段为网络号段+后一段的主机号段

一个网络号:256

IP地址的分类:

A类1.0.0.1---127.255.255.254(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)(2)127.X.X.X是保留地址,用做循环测试用的。

B类128.0.0.1---191.255.255.254172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。

C类192.0.0.1---223.255.255.254192.168.X.X是私有地址

D类224.0.0.1---239.255.255.254

E类240.0.0.1---247.255.255.254

两个DOS命令:

ipconfig 查看本机ip地址

ping 后面跟ip地址。测试本机与指定的ip地址间的通信是否有问题

特殊的IP地址:

127.0.0.1 回环地址(表示本机)

x.x.x.255 广播地址

x.x.x.0 网络地址

获取主机名

/*

* 如果一个类没有构造方法:

* A:成员全部是静态的(Math,Arrays,Collections)

* B:单例设计模式(Runtime)

* C:类中有静态方法返回该类的对象(InetAddress)

* class Demo {

* private Demo(){}

*

* public static Demo getXxx() {

* return new Demo();

* }

* }

*

* 看InetAddress的成员方法:

* public static InetAddress getByName(String host):根据主机名或者IP地址的字符串表示得到IP地址对象

*/

public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// public static InetAddress getByName(String host)
// InetAddress address = InetAddress.getByName("liuyi");
// InetAddress address = InetAddress.getByName("192.168.12.92");
InetAddress address = InetAddress.getByName("192.168.12.63");
 
// 获取两个东西:主机名,IP地址
// public String getHostName()
String name = address.getHostName();
// public String getHostAddress()
String ip = address.getHostAddress();
System.out.println(name + "---" + ip);
}
}

端口

物理端口 网卡口

逻辑端口 我们指的就是逻辑端口

A:每个网络程序都会至少有一个逻辑端口

B:用于标识进程的逻辑地址,不同进程的标识

C:有效端口:0~65535,其中0~1024系统使用或保留端口。

通过360可以查看端口号

协议:

通信的规则

UDP:

把数据打包

数据有限制

不建立连接

速度快

不可靠

TCP:

建立连接通道

数据无限制

速度慢

可靠

举例:

UDP:发短信

TCP:打电话

协议UDP和TCP

UDP

将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快

TCP

建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低

Socket

Socket套接字:

网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

Socket原理机制:

通信的两端都有Socket。

网络通信其实就是Socket间的通信。

数据在两个Socket间通过IO传输。

Udp发送端代码

/*

* UDP协议发送数据:

* A:创建发送端Socket对象

* B:创建数据,并把数据打包

* C:调用Socket对象的发送方法发送数据包

* D:释放资源

*/

public class SendDemo {
public static void main(String[] args) throws IOException {
// 创建发送端Socket对象
// DatagramSocket()
DatagramSocket ds = new DatagramSocket();
 
// 创建数据,并把数据打包
// DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// 创建数据
byte[] bys = "hello,udp,我来了".getBytes();
// 长度
int length = bys.length;
// IP地址对象
InetAddress address = InetAddress.getByName("192.168.12.92");
// 端口
int port = 10086;
DatagramPacket dp = new DatagramPacket(bys, length, address, port);
 
// 调用Socket对象的发送方法发送数据包
// public void send(DatagramPacket p)
ds.send(dp);
 
// 释放资源
ds.close();
}
}

Udp接收端代码

/*

* UDP协议接收数据:

* A:创建接收端Socket对象

* B:创建一个数据包(接收容器)

* C:调用Socket对象的接收方法接收数据

* D:解析数据包,并显示在控制台

* E:释放资源

*/

public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 创建接收端Socket对象
// DatagramSocket(int port)
DatagramSocket ds = new DatagramSocket(10086);
 
// 创建一个数据包(接收容器)
// DatagramPacket(byte[] buf, int length)
byte[] bys = new byte[1024];
int length = bys.length;
DatagramPacket dp = new DatagramPacket(bys, length);
 
// 调用Socket对象的接收方法接收数据
// public void receive(DatagramPacket p)
ds.receive(dp); // 阻塞式
 
// 解析数据包,并显示在控制台
// 获取对方的ip
// public InetAddress getAddress()
InetAddress address = dp.getAddress();
String ip = address.getHostAddress();
// public byte[] getData():获取数据缓冲区
// public int getLength():获取数据的实际长度
byte[] bys2 = dp.getData();
int len = dp.getLength();
String s = new String(bys2, 0, len);
System.out.println(ip + "传递的数据是:" + s);
 
// 释放资源
ds.close();
}
}

图解

UDP代码优化

/*

* 多次启动接收端:

* java.net.BindException: Address already in use: Cannot bind

* 端口被占用。

*/

public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(12345);
 
// 创建一个包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
 
// 接收数据
ds.receive(dp);
 
// 解析数据
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
 
// 释放资源
ds.close();
}
}
 
 
public class SendDemo {
public static void main(String[] args) throws IOException {
// 创建发送端的Socket对象
DatagramSocket ds = new DatagramSocket();
 
// 创建数据并打包
byte[] bys = "helloworld".getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.12.92"), 12345);
 
// 发送数据
ds.send(dp);
 
// 释放资源
ds.close();
}
}

从键盘录入数据进行发送,如果输入的是886那么客户端就结束输入数据。

/*

* 数据来自于键盘录入

* 键盘录入数据要自己控制录入结束。

*/

public class SendDemo {
public static void main(String[] args) throws IOException {
// 创建发送端的Socket对象
DatagramSocket ds = new DatagramSocket();
 
// 封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
 
// 创建数据并打包
byte[] bys = line.getBytes();
// DatagramPacket dp = new DatagramPacket(bys, bys.length,
// InetAddress.getByName("192.168.12.92"), 12345);
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.12.255"), 12345);
 
// 发送数据
ds.send(dp);
}
 
// 释放资源
ds.close();
}
}
 
 
/*
 * 多次启动接收端:
 * java.net.BindException: Address already in use: Cannot bind
 * 端口被占用。
 */
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(12345);
 
while (true) {
// 创建一个包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
 
// 接收数据
ds.receive(dp);
 
// 解析数据
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
}
 
// 释放资源
// 接收端应该一直开着等待接收数据,是不需要关闭
// ds.close();
}
}

多个聊天室

/*

* 通过多线程改进刚才的聊天程序,这样我就可以实现在一个窗口发送和接收数据了

*/

public class ChatRoom {
public static void main(String[] args) throws IOException {
DatagramSocket dsSend = new DatagramSocket();
DatagramSocket dsReceive = new DatagramSocket(12306);
 
SendThread st = new SendThread(dsSend);
ReceiveThread rt = new ReceiveThread(dsReceive);
 
Thread t1 = new Thread(st);
Thread t2 = new Thread(rt);
 
t1.start();
t2.start();
}
}
 
public class ReceiveThread implements Runnable {
private DatagramSocket ds;
 
public ReceiveThread(DatagramSocket ds) {
this.ds = ds;
}
 
@Override
public void run() {
try {
while (true) {
// 创建一个包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
 
// 接收数据
ds.receive(dp);
 
// 解析数据
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
 
}
 
public class SendThread implements Runnable {
 
private DatagramSocket ds;
 
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
 
@Override
public void run() {
try {
// 封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
 
// 创建数据并打包
byte[] bys = line.getBytes();
// DatagramPacket dp = new DatagramPacket(bys, bys.length,
// InetAddress.getByName("192.168.12.92"), 12345);
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.12.255"), 12306);
 
// 发送数据
ds.send(dp);
}
 
// 释放资源
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
 
}

TCP传输

Socket和ServerSocket

建立客户端和服务器端

建立连接后,通过Socket中的IO流进行数据的传输

关闭socket

同样,客户端与服务器端是两个独立的应用程序。

/*

* TCP协议发送数据:

* A:创建发送端的Socket对象

* 这一步如果成功,就说明连接已经建立成功了。

* B:获取输出流,写数据

* C:释放资源

*

* 连接被拒绝。TCP协议一定要先看服务器。

* java.net.ConnectException: Connection refused: connect

*/

public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建发送端的Socket对象
// Socket(InetAddress address, int port)
// Socket(String host, int port)
// Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
Socket s = new Socket("192.168.12.92", 8888);
 
// 获取输出流,写数据
// public OutputStream getOutputStream()
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我来了".getBytes());
 
// 释放资源
s.close();
}
}

服务器代码

/*

* TCP协议接收数据:

* A:创建接收端的Socket对象

* B:监听客户端连接。返回一个对应的Socket对象

* C:获取输入流,读取数据显示在控制台

* D:释放资源

*/

public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建接收端的Socket对象
// ServerSocket(int port)
ServerSocket ss = new ServerSocket(8888);
 
// 监听客户端连接。返回一个对应的Socket对象
// public Socket accept()
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(); //这个不应该关闭
}
}

接受数据并且反馈

public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(9999);
 
// 监听客户端的连接
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();
os.write("数据已经收到".getBytes());
 
// 释放资源
s.close();
// ss.close();
}
}
 
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 9999);
 
// 获取输出流
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();
}
}

客户端键盘录入服务器控制台输出

/*

* 客户端键盘录入,服务器输出到控制台

*/

public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 22222);
 
// 键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 把通道内的流给包装一下
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
 
String line = null;
while ((line = br.readLine()) != null) {
// 键盘录入数据要自定义结束标记
if ("886".equals(line)) {
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
 
// 释放资源
// bw.close();
// br.close();
s.close();
}
}
 
 
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(22222);
 
// 监听客户端连接
Socket s = ss.accept();
 
// 包装通道内容的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
 
// br.close();
s.close();
// ss.close();
}
}

客户端键盘录入,服务器输出文本文件

/*

* 客户端键盘录入,服务器输出文本文件

*/

public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 23456);
 
// 封装键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 封装通道内的数据
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
 
String line = null;
while ((line = br.readLine()) != null) {
if ("over".equals(line)) {
break;
}
 
bw.write(line);
bw.newLine();
bw.flush();
}
 
// bw.close();
// br.close();
s.close();
}
}
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(23456);
 
// 监听客户端连接
Socket s = ss.accept();
 
// 封装通道内的数据
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封装文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
 
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
 
bw.close();
// br.close();
s.close();
// ss.close();
}
}

客户端文本文件,服务器输出到控制台

/*

* 客户端文本文件,服务器输出到控制台

*/

public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建Socket对象
Socket s = new Socket("192.168.12.92", 34567);
 
// 封装文本文件
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封装通道内的流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
 
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
 
br.close();
s.close();
}
}
 
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器Socket对象
ServerSocket ss = new ServerSocket(34567);
 
// 监听客户端连接
Socket s = ss.accept();
 
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
 
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
 

s.close();
}
}

客户端文本文件,服务器输出文本文件

public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 11111);
 
// 封装文本文件
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封装通道内流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
 
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
 
// 释放资源
br.close();
s.close();
}
}
 
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建服务器端的Socket对象
ServerSocket ss = new ServerSocket(11111);
 
// 监听客户端连接
Socket s = ss.accept();
 
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封装文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
 
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
 
bw.close();
s.close();
}
}

上传文件案例并通知

/*

* 按照我们正常的思路加入反馈信息,结果却没反应。为什么呢?

* 读取文本文件是可以以null作为结束信息的,但是呢,通道内是不能这样结束信息的。

* 所以,服务器根本就不知道你结束了。而你还想服务器给你反馈。所以,就相互等待了。

*

* 如何解决呢?

* A:在多写一条数据,告诉服务器,读取到这条数据说明我就结束,你也结束吧。

* 这样做可以解决问题,但是不好。

* B:Socket对象提供了一种解决方案

* public void shutdownOutput()

*/

public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 11111);
 
// 封装文本文件
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封装通道内流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
 
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}

//自定义一个结束标记
//bw.write("over");
//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(11111);
 
// 监听客户端连接
Socket s = ss.accept();// 阻塞
 
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封装文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
 
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
// if("over".equals(line)){
// break;
// }
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.12.92", 19191);
 
// 封装图片文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"林青霞.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(19191);
 
// 监听客户端连接
Socket s = ss.accept();
 
// 封装通道内流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
// 封装图片文件
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("mn.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();
}
}

服务器的代码用线程进行封装,这样可以模拟一个同时接收多人上传文件的服务器。(用循环也可以但是效率低,是单线程的程序)

public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 11111);
 
// 封装文本文件
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封装通道内流
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();
}
}
 
/*
 * 通过while循环可以改进一个服务器接收多个客户端。
 * 但是这个是有问题的。
 * 如果是这种情况,假设我还有张三,李四,王五这三个人分别执行客户端
 * 张三:好好学习.avi(100M)256k
 * 李四:天天向上.mp3(3M)1M
 * 王五:ILoveJava.txt(1k)100M
 */
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建服务器端的Socket对象
ServerSocket ss = new ServerSocket(11111);
 
while (true) {
// 监听客户端连接
Socket s = ss.accept();// 阻塞
 
// 封装通道内的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封装文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
 
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.12.92", 11111);
 
// 封装文本文件
// BufferedReader br = new BufferedReader(new FileReader(
// "InetAddressDemo.java"));
BufferedReader br = new BufferedReader(new FileReader(
"ReceiveDemo.java"));
// 封装通道内流
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(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()));
// 封装文本文件
// BufferedWriter bw = new BufferedWriter(new
// FileWriter("Copy.java"));
 
// 为了防止名称冲突
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();
}
}
 
}

DNS系统解析流程

1.我们每天使用web客户端上网浏览网页。当我们输入www.it18zhang.com时候就可以看到网站内容。这一切是不是很神奇,那么在其背后到底怎么实现流程的呢?

第一步:客户端在用户浏览器输入www.it18zhang.com网站网址,系统首先会查找系统本地的DNS缓存以及hosts文件信息,确定是否存在www.it18zhang.com域名对应的ip解析服务器,一般第一次请求时,DNS缓存是没有记录的,而hosts多在内部临时测试时使用

第二步:如果客户端本地DNS缓存和hosts文件没有www.it18zhang.com域名对应的解析记录,那么系统会把浏览器的解析请求发送给客户端本地设置的DNS服务器地址(通常为LDNS local DNS)解析,如果LDNS服务器本地有对应的解析就会直接返回IP地址给客户端,如果没有则LDNS会分钟继续请求其他的DNS服务器

第三步:LDNS从DNS系统的根(.)开始请求对www.it18zhang.com域名的解析,并针对各个层次DNS服务器系统进行一系列的查找,最终查找到it18zhang.com域名对应的授权DNS服务器,而这个授权的DNS服务器正是企业购买域名时用于管理域名解析的服务器,这个服务器会有it18zhang.com对应的ip地址,如果此时访问没有任何效果。说明没有设置好。

第四步:it18zhang.com域名的授权服务器会把www.it18zhang.com对应的最终ip记录发给lDNS。

第五步:LDNS会把来自DNS服务器对应的ip发给浏览器,并把对应的域名缓存起来,指定的时间不会过期。

时间: 2024-10-08 23:06:46

IT十八掌Java基础 网络编程的相关文章

Java基础——网络编程(一)

本文主要记录网络编程的一些基础知识,学了前班部分,对专业术语有些蒙,但是,收货也是很多很多的.观察了自己计算机的进程,查找其他网络地址的IP,对互联网的层次关系有了更深一步的了解.下面多是概念的摘录,有时间我还要回来再看看,加深理解. 目录: 1.网络编程的基础知识 1.1 网络协议 1.2 tcp /ip 1.3 IP地址 1.4 Port(端口号) 2 UDP/Tcp 3 OSI参考模型 1 网络编程的基础知识 1.1  网络协议 规定了计算机之间连接的物理机械,电器等特性,及计算机间的相互

Java基础——网络编程

一.网络编程概述 概述: Java是 Internet 上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序. Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在 Java 的本机安装系统里,由 JVM 进行控制.并且 Java 实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境. 基础: 网络编程的目的: 网络编程的目的就是指直接或间接地通过网络协议与其它计算机进行通讯. 主要存在的问题: 如何准确地定位网络上一台或多台主机

黑马程序员——JAVA基础-网络编程-TCP

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- TCP传输 两个端点的建立连接后会有一个传输数据的通道,这通道称为流,而且是建立在网络基础上的流,称之为socket流.该流中既有读取,也有写入. tcp的两个端点:一个是客户端,一个是服务端. 客户端:对应的对象,Socket 服务端:对应的对象,ServerSocket TCP客户端: ①:建立tcp的socket服务,最好明确具体的地址和端口.这个对象在创建时,就已经可以对指定ip和端口

梦入IBM之java基础-网络编程

如今我们来谈谈最后的内容:网络编程: 1):TCP中是线程与线程进行通讯!内部的执行机制是这种:先有一个线程去监听某个port.然后假设有Socket连接上来了以后,server会生成一个Socket对象与其                进行通讯! 2):通过URL对象能够获得某个某个站点的输入流.(可是这个输入流也是相对于程序的!返回的是一个InputStream的子类!) URL url = new URL("http://www.baidu.com"); HttpURLConn

黑马程序员——java基础---网络编程

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.网络通讯 概念:网络间数据的传输.交互. 三要素:IP地址.端口号.传输协议. ——>IP地址 1.网络中设备的标识 2.单纯的IP地址不易记忆,可用主机名替代. 3.如果本机上没有配置任何IP地址的情况下,本机默认的IP地址为127.0.0.1 本地回环地址:127.0.0.1  主机名:localhost 用处:检验本机网卡是否运行正常等. ——>端口号 概念:用于标识进程的数字称为

java基础——网络编程基础TCP,URL

TCP部分 new socket对象 package ip; /* 1.通过IP地址和域名new InetAddress对象 2.本地回路地址:127.0.0.1 对应localhost,表示本地主机 3.IP地址和端口号接在一起组成一个socket,类似于网络节点 @author zsben @create 2020-01-07 15:34 */ import java.net.InetAddress; import java.net.UnknownHostException; public

Java基础-网络编程

package com.net; /** * 1.什么是网络?什么是计算机网络? * 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大.功能强的网络系统, * 从而使众多的计算机可以方便地互相传递信息,共享硬件.软件.数据信息等资源 * 2.计算机网络的基本功能? * 资源共享 * 信息传输与集中处理 * 均衡负荷与分布处理 * 综合信息服务 * 3.计算机网络协议? * 计算机网络中实现通信必须有一些约定即通信协议,对速率.传输代码.代码结构.传 输控制步骤.出错控制等制

IT十八掌Java基础 设计模式

      Day20 扩展知识 面向对象思想设计原则 设计模式 设计模式的分类 常见的设计模式 简单工厂模式和工厂方法模式(接口) 模版设计模式(抽象类) 装饰设计模式(IO流) 单例设计模式(多线程) 适配器模式(GUI) 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设计原则 单一职责原则 开闭原则 里氏替换原则 依赖注入原则 接口分离原则 迪米特原则   单一职责原则 其实就是开发人员经常说的"高内聚,低耦合" 也

黑马程序员——Java基础——网络编程

第一讲 网络概述 1.网络通信三要素:电脑IP地址.软件本地端口号.网络间传输协议(国际通用的TIP/IP,还有很多其他的) 小知识:-ping 127.0.0.7可以测试网卡用 2.网络模型图列: 用户在运用层发出的数据,经过逐层打包后通过物理层传输到另一个模型中,然后逐层分解,找到端口,被另一个用户获得 IP地址:InetAddress• 网络中设备的标识• 不易记忆,可用主机名• 本地回环地址:127.0.0.1 主机名:localhost 使用java.net包中的InetAddress