网络编程
网络编程:即是通过网络,连接不同的计算机(程序),进行通信(数据交互)。
网络模型:
网络通信三大要素:
1、IP地址:唯一标识,同通过IP地址来确定多台计算机的地址。
ip地址共分为:A、B、C、D、E五类,均由网络号码和主机地址组成。
A类:【网络号码】.【本地计算机号码】.【本地计算机号码】.【本地计算机号码】
B类:【网络号码】.【网络号码】.【本地计算机号码】.【本地计算机号码】
C类:【网络号码】.【网络号码】.【网络号码】.【本地计算机号码】
2、端口:用于标识进程的逻辑地址
端口分为两种:物理端口(网卡口)和逻辑端口
逻辑端口的有效端口:0~65535,其中0~1024是系统的使用的或是保留端口
不同的进程,逻辑端口也不同(唯一标识), 每个网络程序都至少会有一个逻辑端口
3、协议:通信的规则
udp协议和tcp协议
UDP协议
UDP协议:提供面向事务的简单不可靠信息传送服务,每个数据包的大小限制在64k以内,由于不需要建立连接,速度快。(容易丢包,且无法保证数据的顺序)
UDP使用DatagramSocket类来收、发数据,使用DatagramPacket类(数据报包)来打包数据。
DatagramSocket和DatagramPacket的简单使用(UDP协议):
package socketDemo;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//UDP聊天室服务器端线程
public class UDPChatRoomByReceiveDemo implements Runnable{
@Override
public void run() {
DatagramSocket receiveDS = null;
String ip = "";
String massage = "";
byte[] bytes = new byte[1024];
try {
//创建udp服务对象(指定端口号)
receiveDS = new DatagramSocket(12345);
//创建数据报包对象,用于接收数据
DatagramPacket receiveDP = new DatagramPacket(bytes, bytes.length);
while(true){
//接收数据
receiveDS.receive(receiveDP);
//将数据打印到控制台
ip = receiveDP.getAddress().getHostAddress();
massage = new String(receiveDP.getData(), 0, receiveDP.getLength());
System.out.println("ip: [" + ip + "]" + "---->" + "massage: [" + massage + "]");
}
} catch (IOException e) {
e.printStackTrace();
}
//释放资源
if(receiveDS != null){
receiveDS.close();
}
}
}
package socketDemo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//UDP聊天室客户端线程
public class UDPChatRoomBySendDemo implements Runnable{
@Override
public void run() {
DatagramSocket sendDS = null;
BufferedReader br = null;
String line = "";
byte[] bytes = new byte[1024];
try {
//创建udp服务对象
sendDS = new DatagramSocket();
//创建数据报包,用于打包数据(1x.2x.3x.255 为广播地址,数据会发向3x网段下的所有ip)
DatagramPacket sendDP = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.199.255"), 12345);
//获取键盘录入的数据(当录入quit时关闭客户端线程)
br = new BufferedReader(new InputStreamReader(System.in));
while((line = br.readLine()) != null && !line.equals("quit")){
sendDP.setData(line.getBytes());
//发送数据
sendDS.send(sendDP);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//释放资源
if(sendDS != null){
sendDS.close();
}
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package socketDemo;
public class UDPChatRoomDemo {
public static void main(String[] args) {
//创建服务器和客户端线程对象
UDPChatRoomByReceiveDemo receiveDemo = new UDPChatRoomByReceiveDemo();
UDPChatRoomBySendDemo sendDemo = new UDPChatRoomBySendDemo();
Thread receiveThread = new Thread(receiveDemo);
Thread sendThread = new Thread(sendDemo);
//启动线程
receiveThread.start();
sendThread.start();
}
}
TCP协议
TCP协议:是一种面向连接的、可靠的、基于字节流的传输层通信协议,通过三次握手完成连接,因此速度稍慢。(每次发送数据需要限制数据的大小,否则可能会造成发送超时)
tcp的服务器端使用ServerSocket类的accept方法来监听链接,客户端使用Socket类,双方的数据以流的方式相互通信
ServerSocket和Socket的简单使用:
package socketDemo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
//tcp协议聊天室服务端
public class TCPChatRoomByReceiveDemo implements Runnable{
@Override
public void run() {
ServerSocket ss = null;
Socket s = null;
String ip;
String massage;
try {
//创建服务端对象
ss = new ServerSocket(23456);
//监听连接,该方法会返回与服务器端相连接的客户端的Socket对象
s = ss.accept();
//通过输入流获取数据并打印在控制台
BufferedReader receiveBR = new BufferedReader(new InputStreamReader(s.getInputStream()));
ip = s.getInetAddress().getHostAddress();
while((massage = receiveBR.readLine()) != null){
System.out.println("ip: [" + ip + "]---->massage: [" + massage + "]");
//返回结果
BufferedWriter receiveBW = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
receiveBW.write("数据接收成功");
receiveBW.newLine();
receiveBW.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
if(s != null){
try {
//释放资源(仅释放s对象即可,关闭当前链接,服务端可继续运行)
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package socketDemo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
//tcp聊天室客户端
public class TCPChatRoomBySendDemo implements Runnable{
@Override
public void run() {
Socket s = null;
BufferedWriter sendBW = null;
BufferedReader sendBR = null;
BufferedReader in = null;
String massage;
try {
//创建服务端对象
s = new Socket("192.168.199.215", 23456);
//创建输入流读取键盘录入的数据
in = new BufferedReader(new InputStreamReader(System.in));
//创建输出流和输入流用于写入数据
sendBW = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
sendBR = new BufferedReader(new InputStreamReader(s.getInputStream()));
//将数据写入输出流,输入quit关闭客户端(使用shutdownOutput()或shutdownInput()可以关闭流)
while((massage = in.readLine()) != null && !massage.equals("quit")){
sendBW.write(massage);
sendBW.newLine();
sendBW.flush();
//获取返回值并在控制台打印
massage = sendBR.readLine();
System.out.println(massage);
}
} catch (IOException e) {
e.printStackTrace();
}
if(s != null){
try {
//释放资源
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(sendBR != null){
try {
//释放资源
sendBR.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package socketDemo;
public class TCPChatRoomDemo {
public static void main(String[] args) {
//创建服务器和客户端线程对象
TCPChatRoomByReceiveDemo receiveDemo = new TCPChatRoomByReceiveDemo();
TCPChatRoomBySendDemo sendDemo = new TCPChatRoomBySendDemo();
Thread receiveThread = new Thread(receiveDemo);
Thread sendThread = new Thread(sendDemo);
//启动线程
receiveThread.start();
sendThread.start();
}
}