网络编程
网络编程的本质是 两个设备之间的数据交换 ,在JAVA学习中,设备主要指计算机。
网络编程需要依赖于计算机网络,这样才能准确的定位和连接计算机。所以下面简单说一下计算机网络的概念.
基本概念
1计算机网络
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
简单的说,就是把不同地方的多台计算机连接起来,让他们直接按可以通讯。
2网络通信的要素
那么,和才能如何实现网络的通信?
也就是网络通信的要素是什么。
2.1 IP
在现实生活中,如果要打电话则需要知道对应人的电话号码。在网络中也是这样,需要知道一个设备的位置,则需要使用该设备的IP地址,具体的连接过程由硬件实现,我们不需要过多的关心。
关心。
IP地址是一个规定,有IPv4,与IPV6 。
IPv4既由4个0-255之间的数字组成,在计算机内部存储时只需要4个字节即可。在计算机中,IP地址是分配给网卡的,每个网卡有一个唯一的IP地址。
如果一个计算机有多个网卡,则该台计算机则拥有多个不同的IP地址,在同一个网络内部,IP地址不能相同。IP地址的概念类似于电话号码、身份证这样的概念。
#### 域名
由于IP地址不方便记忆,所以有专门创造了域名,其实就是给IP取一个字符的名字,例如163.com、4399.com等。IP和域名之间存在一定的对应关系。如果把IP地址类比成身份证号的话,那么域名就是姓名。
注意:其实在网络中只能使用IP地址进行数据传输,所以在传输以前,需要把域名转换为IP,这个由称作DNS的服务器专门来完成。
2.2 端口
为了在一台设备上可以运行多个程序,人为的设计了端口(Port)的概念
规定一个设备有65536个端口,每个端口对应一个唯一的程序。每个网络程序,无论是客户端还是服务器端,都对应一个或多个特定的端口号。
使用端口号,可以找到一台设备上唯一的一个程序。
所以如果想要和某个程序连接,需要知道ip和端口号。
注意:0-1024之间多被操作系统占用,所以实际编程时一般采用1024以后的端口号。
2.5通信协议
协议是网络编程中一个非常重要的概念,指的是传输数据的格式。因为大家在网络中需要传输各种各样的信息,在程序中获得到的都是一组数值。
如何阅读这些数值呢,就需要提前规定好这组数据的格式,在客户端按照该格式生成发送数据,服务器端按照该格式阅读该数据,然后在按照一定的格式生成数据反馈给客户端,客户端再按照该格式阅读数据。现实中类似的例子就是电报编码,每个数字都是用特定的数据表达。
最重要的协议是UDP和TCP
类比现实世界的话。
TCP : 类似打电话
只需要建立一次连接,就可以多次传输数据。
就像电话只需要拨一次号,就可以实现一直通话一样,保证传输的数据可靠。
优点是稳定可靠,缺点是建立连接和维持连接的代价高,传输速度不快。
UDP :类似发短信
不建立稳定的连接,类似于发短信息。
每次发送数据都直接发送。发送多条短信,就需要多次输入对方的号码。该传输方式不可靠,数据有可能收不到,系统只保证尽力发送。
优点是开销小,传输速度快,缺点是数据有可能会丢失。
代码举例
java中已经将ip封装。下面是获得ip地址的方法和获得主机名的方法
public class Mytest1 {
public static void main(String[] args) {
try {
//获得ip地址的类
//三种常用的获得本地ip的方法
InetAddress address = InetAddress.getByName("localhost");
System.out.println(address);
InetAddress address1 = InetAddress.getByName("127.0.0.1");
System.out.println(address1);
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
//获得网络ip的方法
//InetAddress address3 = InetAddress.getByName("www.baidu.com");
//将ip拆分,获得主机名和ip的方法
String hostName = localHost.getHostName();
System.out.println(hostName);
String address2 = localHost.getHostAddress();
System.out.println(address2);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
public class MyTest2 {
public static void main(String[] args) {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 900);
System.out.println(address);
String hostName1 = address.getHostName();
System.out.println(hostName1);
InetAddress address2 = address.getAddress();
System.out.println(address2);
InetSocketAddress address1 = new InetSocketAddress("local", 900);
System.out.println(address1);
String hostName = address1.getHostName();
System.out.println(hostName);
}
}
下面是用tcp做文件上传与下载的例子
public class TCPSendPhoto {
//发送图片,并接收服务器发送的通知
public static void main(String[] args) throws IOException {
//建立联系
Socket socket = new Socket(InetAddress.getByName("localhost"), 900);
//获得流输出图片
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream(new File("F:\\java\\demo\\网络编程\\src\\org\\westos\\demo\\wenjiu.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer,0,len);
}
socket.shutdownOutput();
//等客户端接受完毕关闭连接
InputStream is = socket.getInputStream();
int len2;
byte[] buffer2 = new byte[1024];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len2 = is.read(buffer2)) != -1) {
bos.write(buffer2,0,len2);
}
System.out.println(bos.toString());
bos.close();
is.close();
fis.close();
os.close();
socket.close();
}
}
public class TCPReceivePhoto {
//接收图片并打印出去
public static void main(String[] args) throws IOException {
//创建连接
ServerSocket serverSocket = new ServerSocket(900);
Socket socket = serverSocket.accept();
//获得流
InputStream is = socket.getInputStream();
//流操作,打印图片
FileOutputStream fis = new FileOutputStream("zhangwuji.jpg");
int len;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
fis.write(buffer, 0, len);
}
//打印结束,通知系统与客户端
OutputStream os = socket.getOutputStream();
os.write("接收完毕".getBytes());
//关闭资源
os.close();
fis.close();
is.close();
socket.close();
serverSocket.close();
}
}
下面是用udp做交谈的例子
思路是定义两个多线程的类,然后分别启动。
public class Receive implements Runnable {
DatagramSocket socket = null;
private String who;
private int port;
//自己的端口,谁发的消息
public Receive(int port, String who) {
this.port = port;
this.who = who;
try {
//设置端口
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
//阻塞式接收
try {
//准备接收
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
byte[] data = packet.getData();
String language = new String(data, 0, data.length);
//打印在屏幕上
System.out.println(who + ": " + language);
//结束条件
if (language.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭资源
if (null != socket) {
socket.close();
}
}
}
public class Send implements Runnable {
BufferedReader reader = null;
DatagramSocket socket = null;
//发送消息
int toport;
int port;
public Send(int toport, int port) {
this.toport = toport;
this.port = port;
try {
//创建连接
socket = new DatagramSocket(port);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
//获得消息
try {
String language = reader.readLine();
byte[] data = language.getBytes();
//打包
DatagramPacket packet = new DatagramPacket(data, 0, data.length, InetAddress.getByName("127.0.0.1"), toport);
//寄包裹
socket.send(packet);
//判断退出条件
if (language.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭资源
if (socket != null) {
socket.close();
}
}
}
public class Teacher {
public static void main(String[] args) {
new Thread(new Receive(2000,"学生")).start();
new Thread(new Send(1000,7787)).start();
}
}
public class Student {
public static void main(String[] args) {
new Thread(new Receive(1000,"老师")).start();
new Thread(new Send(2000,8878)).start();
}
}