一、网络编程概述
网络编程:就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络模型:一般是指OSI(Open System Interconnection开放系统互连)参考模型、TCP/IP参考模型
二、网络编程三要素
1.IP:
a.概念:
所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址。按照TCP/IP规定,
IP地址用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节。
例如一个采用二进制形式的IP地址是"11000000101010000000000101100100",
这么长的地址,人们处理起来也太费劲了。
为了方便人们的使用,IP地址经常被写成十进制的形式,中间使用符号"."分开不同的字节。
于是,上面的IP地址可以表示为“10.0.0.1”。
IP地址的这种表示法叫做"点分十进制表示法",这显然比1和0容易记忆得多。
最小IP:00000000.00000000.00000000.00000000:十进制:0.0.0.0
最大IP:11111111.11111111.11111111.11111111:十进制:255.255.255.255
b.IP地址的组成
IP地址 = 网络号码+主机地址
A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码
B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码
C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码
局域网内的电脑在什么情况下可以互相访问:在同一网段;
怎么来区分同一网段:
"子网掩码":
例如:有如下IP:
1).192.168.1.10
2).192.168.1.20
3).192.168.2.30
1.子网掩码:为:255.255.255.0(二进制:11111111.11111111.11111111.00000000)
(注意:子网掩码中全部表示为1的作为"网络号码")
1和2可以互访;
2.子网掩码:255.255.0.0(二进制:11111111.11111111.00000000.00000000)
1和2和3都可以互访;
特殊地址:
127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1
DOS命令 ipconfig:查看本机IP地址
xxx.xxx.xxx.0 网络地址
xxx.xxx.xxx.255 广播地址
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
那么,我们如果获取和操作IP地址呢?
为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress 供我们使用。
/*
* java.net.InetAddress(类):此类表示互联网协议 (IP) 地址。
* 获取任意主机:getByName(静态方法)
* 机名:getHostName
* 主机Ip地址:getHostAddress
*/
public class Demo {
public static void main(String[] args) {
try {
InetAddress address = InetAddress.getByName("WAK-20150115SMD");
String hostName = address.getHostName();
String ip = address.getHostAddress();
System.out.println("计算机名:" + hostName + " IP:" + ip);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
2.端口:
1).物理端口:网卡口;
2).逻辑端口:由操作系统管理的,在一个"物理端口"的情况下,为了能同时运行多个"网络应用程序" 这时操作系统提供了"逻辑端口";
A.我们讲的"端口"就是"逻辑端口";
B.逻辑端口的范围:0--65535;
C.一个应用程序可以同时占用多个端口;
D.一个端口,在某一时刻,只能由一个应用程序占用;
E.0--1024:是由操作系统使用的,我们最好不要用;
3.协议:
1).TCP,UDP,FTP,HTTP.......
2).UDP协议:
1.面向无连接:类似于"广播","有线电视"
2.数据需要打包发送;
3.数据大小有限制:64K以内;
4.因为无连接,所以属于不可靠的协议,但速度快;
3).TCP协议:
1.面向连接:类似于"打电话"
2.可以进行大量数据的传输;
3.由于需要连接,建立连接就要双方确认,所有速度慢;
三、Socket
Socket套接字:
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
Socket原理机制:
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
四、UDP协议编程
//发送端:
//1.实例化DatagramSocket();
DatagramSocket socket = new DatagramSocket();
//2.准备数据:IP、端口、数据
InetAddress add = InetAddress.getByName("Lenovo-PC");
int port = 8888;
byte[] byteArray = "你好".getBytes();
//3.准备数据报:
DatagramPacket packet = new DatagramPacket(byteArray,byteArray.length,add,port);
//4.发送:
socket.send(packet);
//5.释放资源:
socket.close();
//接收端:
//1.实例化DatagramSocket
DatagramSocket socket = new DatagramSocket(8888);
//2.准备一个空的byte[]数组
byte[] byteArray = new byte[1024];
//3.准备一个空的DatagramPacket
DatagramPacket packet = new DatagramPacket(byteArray,byteArray.length);
//4.等待信息
socket.receive(packet);
//5.获取信息:地址、端口、数据主体
String ip = packet.getAddress().getHostAddress();
int port = packet.getPort();
byte[] infoArray = packet.getData();
String info = new String(infoArray,0,packet.getLength());
System.out.println("ip:"+ip+",端口号:"+port+"获取的信息:" + info);
//6.释放资源
socket.close();
五
、TCP协议编程
//发送端:
//1.实例化一个Socket
Socket socket = new Socket("192.168.38.91",8888);
//2.获取输出流
OutputStream out = socket.getOutputStream();
//3.输出,一次输出一个字节数组
out.write("你好".getBytes());
//4.释放资源
out.close();
socket.close();
//接收端:
//1.实例化一个ServerSocket
ServerSocket server = new ServerSocket(8888);
//2.获取输入流
Socket accept = server.accept();
InputStream in = accept.getInputStream();
//3.一次读取一个字节数组
String ip = accept.getInetAddress().getHostAddress();
byte[] byteArray = new byte[1024];
int len = in.read(byteArray);
String s = new String(byteArray,0,len);
System.out.println("IP:"+ip+",接收到的数据:"+s);
//4.释放资源
in.close();
accept.close();
server.close();
TCP传输容易出现的问题:
客户端连接上服务端,两端都在等待,没有任何数据传输。
通过例程分析:
因为read方法或者readLine方法是阻塞式。
解决办法:
自定义结束标记
使用shutdownInput,shutdownOutput方法。
TCP练习_TCP协议上传图片并给出反馈
/*
* TCP协议上传图片并给出反馈
*
* 客户端:
*
* 1.实例化一个Socket;
* 2.获取网络输出流;
* 3.实例化一个文件输入流(字节流(必须));
* 4.循环读取文件内容,一次读取一个字节数组;
* 一次发送一个字节数组;
* 5.释放资源;
*/
public class Client {
public static void main(String[] args) throws IOException{
Socket socket = new Socket("192.168.30.241",8888);
OutputStream netOut = socket.getOutputStream();
FileInputStream fileIn = new FileInputStream("C:\\aaa\\cxy.bmp");
byte[] byteArray = new byte[1024];
int len = 0;
while((len = fileIn.read(byteArray)) != -1){
netOut.write(byteArray,0,len);
}
//结束输出流
socket.shutdownOutput();
//***************接收反馈***************//
InputStream netIn = socket.getInputStream();
byte[] byteInfo = new byte[1024];
len = netIn.read(byteInfo);
String str = new String(byteInfo,0,len);
System.out.println("客户端接收到反馈:" + str);
//释放资源
netIn.close();
netOut.close();
fileIn.close();
socket.close();
System.out.println("客户端结束!");
}
}
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
//网络输入流
InputStream netIn = socket.getInputStream();
//文件输出流
FileOutputStream fileOut = new FileOutputStream("demo12_cxy_copy.bmp");
//一次读取一个字节数组
byte[] byteArray = new byte[1024];
int len = 0;
System.out.println("服务器端开始接收数据......");
while((len = netIn.read(byteArray)) != -1){
fileOut.write(byteArray,0,len);
}
//**************给出反馈*************//
System.out.println("服务器端接收完毕,发送反馈信息......");
OutputStream netOut = socket.getOutputStream();
netOut.write("接收完毕!".getBytes());
//释放资源
netOut.close();
fileOut.close();
netIn.close();
socket.close();
server.close();
System.out.println("服务器端完毕!");
}
}
TCP练习_关于多个客户端上传到一个服务器的思考
public class ClientThread extends Thread {
private int index;
public ClientThread(int index){
this.index = index;
}
@Override
public void run() {
//连接服务器
try {
Socket socket = new Socket("192.168.30.241",8888);
//网络输出流
OutputStream netOut = socket.getOutputStream();
//文件输入流
FileInputStream fileIn = new FileInputStream("C:\\ccc\\" + index + ".png");
//一次读取一个字节数组
byte[] byteArray = new byte[1024];
int len = 0;
while((len = fileIn.read(byteArray)) != -1){
netOut.write(byteArray,0,len);
}
//释放资源
fileIn.close();
netOut.close();
socket.close();
System.out.println("文件:" + index + ".png 上传完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ServerThread extends Thread {
public int index ;
private Socket socket ;
//此索引,跟客户端的索引不是一一对应的;
public ServerThread(int index,Socket socket){
this.index = index;
this.socket = socket;
}
@Override
public void run() {
//获取网络输入流
try {
InputStream netIn = socket.getInputStream();
FileOutputStream fileOut = new FileOutputStream(index + ".png");
byte[] byteArray = new byte[1024];
int len = 0;
while((len = netIn.read(byteArray)) != -1){
fileOut.write(byteArray,0,len);
}
fileOut.close();
netIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//文件的输出流
}
}
public class Client {
public static void main(String[] args) {
//模拟10个客户端同时连接服务器
for(int i = 1 ; i <= 10 ;i ++){
new ClientThread(i).start();
}
}
}
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket server = new ServerSocket(8888);
int index = 1;
while(true){
Socket socket = server.accept();
//启动线程;
new ServerThread(index++,socket).start();
}
}
}