网络编程
目的
直接或间接地通过网络协议与其它计算机进行通讯
想要编写网络程序时所面临的问题
-
如何准确地定位网络上一台或多台主机
-
找到主机后如何可靠高效地进行数据传输
几个概念
计算机网络(Network):就是将地理位置不同的网络终端设备,通过网络传输介质连接起来,在网络操作系统和网络通信协议的管理和协调下,实现资源共享和信息传递的功能。
IP 地址(Internet Protocol Address):是互联网协议特有的一种地址。它是一台终端设备在网络中的唯一标识
IP地址有两种分类:IPv4(4个单字节无符号数字排列组合形成的唯一标识) 和 IPv6(8个16位的16进制无符号数字排列组合形成的唯一标识)
本地自回环网络标识:127.0.0.1, 网络名是localhost
端口(Port):标识正在计算机上运行的程序,不同的进程有不同的端口号。网络中的计算机是通过 IP 地址来代表其身份的,它只能表示某台特定的计算机,但是一台计算机上可以同时提供很多个服务,如数据库服务、FTP 服务、Web 服务等,我们就通过端口号来区别相同计算机所提供的这些不同的服务。端口号被规定为一个 16 位的整数 0~65535。其中,0~1023被预先定义的服务通信占用除非我们需要访问这些特定服务,否则,就应该使用 1024~65535 这些端口中的某一个进行通信,以免发生端口冲突
套接字(Socket):端口号与IP地址的组合得出一个网络套接字:Socket
协议(Protocal):网络协议的简称,网络协议是通信计算机双方必须共同遵从的一组约定。 这是一整套对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准的解决方案。只有遵守这个约定,计算机之间才能相互通信交流.为了使数据在网络上从源到达目的,网络通信的参与方必须遵循相同的规则,常用的协议如 TCP,UDP,HTTP 等
通信协议分层的思想:由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展
关于TCP/IP的认知
TCP/IP 以其两个主要协议:传输控制协议 (TCP) 和网络互联协议(IP) 而得名,实际上是一组协议,包括多个具有不同功能且互为关联的协议。IP(Internet Protocol)协议是网络层的主要协议,支持网间互连的数据通信。
TCP&UDP的各自的特点
TCP协议:
使用TCP协议前,须先建立TCP连接,形成传输数据通道
传输前,采用“三次握手”方式,是可靠的。通过 TCP 连接传送的数据,无差错、不丢失、不重复,并且按序到达。
TCP协议进行通信的两个应用进程:客户端、服务端。每一条 TCP 连接只能有两个端点,每一条 TCP 连接只能是点对点的(一对一)。
在连接中可进行大数据量的传输,并且数据的传输是基于字节流的
传输完毕,需释放已建立的连接,效率低
UDP协议:
将数据、源、目的地封装成数据包,不需要建立连接
每个数据报的大小限制在64K内
因无需连接,故是不可靠的
发送数据结束时无需释放资源,速度快
关于TCP中的三次握手&四次挥手的认知(面试题)
TCP编程
客户端和服务端,基于Socket套接字编程
TCP案例:客户端向服务端发送文本信息
编写TCP客户端
public class TCPClient1Test {
public static void main(String[] args) throws IOException {
InetAddress serverAddr = InetAddress.getLocalHost();
//1.创建一个Socket连接对象
Socket socket = new Socket(serverAddr, 8999);
//2.向服务端输出字节流的对象
OutputStream os = socket.getOutputStream();
//3.发送信息
PrintWriter writer = new PrintWriter(new OutputStreamWriter(os));
writer.println("hello ! 你好! 我是Client..");
//4.收尾
writer.flush();
writer.close();
os.close();
//4.1TCP的连接必须被释放
socket.close();
}
}
编写TCP服务端
public class TCPServer1Test {
public static void main(String[] args){
ServerSocket server = null;
Socket clientSocket = null;
InputStream is = null;
BufferedReader reader = null;
try {
//1.创建服务端Socket对象
server = new ServerSocket(8999);
//2.监听客户端的Socket请求
clientSocket = server.accept();
//3.以输入流的方式获取客户端向服务端输入的内容
is = clientSocket.getInputStream();
//3.x 做接收到流信息后,应该处理的业务
reader = new BufferedReader(new InputStreamReader(is));
String input = "";
while( (input = reader.readLine()) != null ) {
System.out.println("IP地址为:"+clientSocket.getInetAddress().getHostAddress()+"客户端发送的信息:" + input);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(is !=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(reader !=null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//4.释放连接
if(clientSocket !=null) {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
TCP案例:客户端向服务端发送文件(上传)
编写TCP客户端
public class TCPClient2Test {
public static void main(String[] args) throws IOException {
InetAddress serverAddr = InetAddress.getLocalHost();
// 1.创建一个Socket连接对象
Socket socket = new Socket(serverAddr, 8999);
// 2.向服务端输出字节流的对象
OutputStream os = socket.getOutputStream();
// 3.发送文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("G:/多线程(下).md")));
BufferedOutputStream bos = new BufferedOutputStream(os);
int input = -1;
while ( (input=bis.read()) != -1) {
bos.write(input);
}
// 4.收尾
bos.flush();
//给一个本次流结束的标识
socket.shutdownOutput();
bos.close();
bis.close();
// 4.1TCP的连接必须被释放
socket.close();
}
}
编写TCP服务端
public class TCPServer2Test {
public static void main(String[] args){
ServerSocket server = null;
Socket clientSocket = null;
InputStream is = null;
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
//1.创建服务端Socket对象
server = new ServerSocket(8999);
//2.监听客户端的Socket请求
clientSocket = server.accept();
//3.以输入流的方式获取客户端向服务端输入的内容
is = clientSocket.getInputStream();
//3.x 做接收到流信息后,应该处理的业务
bos = new BufferedOutputStream(new FileOutputStream(new File("upload.md")));
bis = new BufferedInputStream(is);
int input = -1;
while( (input = bis.read()) != -1 ) {
bos.write(input);
}
System.out.println("接收IP地址为:"+clientSocket.getInetAddress().getHostAddress()+"文件完毕!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if(bos !=null) {
try {
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is !=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bis !=null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//4.释放连接
if(clientSocket !=null) {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP编程
编写发包程序案例
public class UDPSenderTest {
public static void main(String[] args) throws IOException {
DatagramSocket sendSocket = new DatagramSocket();
byte[] buf = "你好UDP的接收方,我是发送方".getBytes();
InetAddress localAddress = InetAddress.getLocalHost();
DatagramPacket sendP = new DatagramPacket(buf, 0, buf.length, localAddress, 9090);
sendSocket.send(sendP);
sendSocket.close();
}
}
编写接包程序案例
public class UDPGetterTest {
public static void main(String[] args) throws Exception{
DatagramSocket sendSocket = new DatagramSocket(9090);
byte[] buf = new byte[1024];
DatagramPacket sendP = new DatagramPacket(buf, 0, buf.length);
sendSocket.receive(sendP);
System.out.println("接收的UDP包的内容为:"+new String(sendP.getData(), 0, sendP.getLength()));
sendSocket.close();
}
}
URL编程
public class URLTest {
public static void main(String[] args) throws Exception{
URL url = new URL("http://www.kfzimg.com/G05/M00/6A/AF/p4YBAFf3CNmAEei9AAIMbhFsIJk732_b.jpg");
URLConnection connection = url.openConnection();
connection.connect();
InputStream is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("download_thinking_in_java.jpg")));
int input = -1;
while ( (input=bis.read())!=-1) {
bos.write(input);
}
bos.flush();
bos.close();
is.close();
bis.close();
}
}
InputStream bis = new BufferedInputStream(is);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("download_thinking_in_java.jpg")));
int input = -1;
while ( (input=bis.read())!=-1) {
bos.write(input);
}
bos.flush();
bos.close();
is.close();
bis.close();
}
}