计算机网络:是将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程:在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换。
1.IP地址:要想让网络中的计算机能够相互通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,而IP地址就是这个标识号。也就是设备的标识。
2.端口:网络的通信本质上是两个应用程序的通信。每台计算机都有很多应用程序,那么网络在通信时,如何区分这些应用程序呢?如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的应用程序,也就是应用程序的标识。
3.协议:通过计算机网络可以使多台计算机实现连接,位于同一网络的计算机在进行连接和通信时需要遵守一定的规则,这些连接和通信规则被称为网络通信协议,他对数据的传输格式、传输速率、传输步骤等做了统一的规定,通信双方必须同时遵守才能完成数据交换。常见的协议有UDP协议和TCP协议。
常用命令:
1.ipconfig:查看本机的IP地址
2.ping IP地址:检查网络是否连通
特殊地址:
127.0.0.1 :是回送地址,可以代替本机地址,一般用来测试使用
为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress供我们使用
InetAddress:此类表示Internet协议(IP)地址
方法名 | 说明 |
static InetAddress getByName(String host) | 确定主机名称的IP地址。主机名称可以是机器名称也可以是IP地址。 |
String getHostName() | 获取此IP地址的主机名 |
String getHostAddress() | 获取文本显示中的IP地址字符串 |
package com.it;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.SortedMap;
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
InetAddress address = InetAddress.getByName("192.168.1.7");//这里也可以是主机名
String name = address.getHostName();
String ip = address.getHostAddress();
System.out.println("主机名:"+name);
System.out.println("IP地址:"+ip);
}
}
端口:设备上应用程序的唯一标识
协议:计算机网络中,连接和通信的规则被称为网络通信协议
UDP协议是一种不可靠的网络协议,它在通信两端各建立一个Socket对象,但是这两个Socket只是发送和接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端与服务器的概念
Java提供了DatagramSocket类作为基于UDP协议的Socket
步骤:
1.创建发送端的Socket对象(DatagramSocket)
DatagramSocket() //构造数据报套接字并将其绑定到本地主机的任何端口
2.创建数据,并把数据打包
DatagramPacket(byte[] buf,int length,InetAddress address,int port) //构造一个数据报,发送长度为length的数据报到指定主机上的指定端口号
3.调用DatagramSocket对象的方法发送数据
void send(DatagramPacket p) //从此套接字发送数据包
4.关闭发送端
void close() //关闭数据报套接字
步骤:
1.创建接收端的Socket对象(DategramSocket)
DatagramSocket(int port)
2.创建一个数据包用于接收数据
DatagramPacket(byte[] buf,int length)
3.调用DatagramSocket对象的方法接收数据
void receive(DatagramPacker dp)
4.解析数据包,并把数据在控制台上显示
byte[] getData()
int getLength()
5.关闭接收端
void close()
//ReceiveDemo.java
package com.itUDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiveDemo1 {
public static void main(String[] args) throws IOException {
//创建接收端的Socket对象(DategramSocket)
DatagramSocket ds = new DatagramSocket(2000);
//创建一个数据包用于接收数据
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//调用DatagramSocket对象的方法接收数据
ds.receive(dp);
//解析数据包,并把数据在控制台上显示
byte[] data = dp.getData();
String datas = new String(data);
System.out.println("数据是:"+datas);
//关闭接收端
ds.close();
}
}
//SendDemo.java
package com.itUDP;
import java.io.IOException;
import java.net.*;
public class SendDemo1 {
public static void main(String[] args) throws IOException {
//创建发送端的Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket();
//创建数据,并把数据打包
byte[] bys = "你好,UDP!".getBytes();
int length = bys.length;
InetAddress address = InetAddress.getByName("192.168.1.7");
int port = 2000;
DatagramPacket dp = new DatagramPacket(bys,length,address,port);
//调用DatagramSocket对象的方法发送数据
ds.send(dp);
//关闭发送端
ds.close();
}
}
按照下面要求实现程序:
UDP发送数据:数据来自于键盘输入,直到输入的数据是886,发送数据结束。
UDP接收数据:因为接收端不知道接收数据什么时候停止发送,故采用死循环接收。
//ReceiveDemo.java
package com.itUDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiveDemo2 {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(2001);
while(true){
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
ds.receive(dp);
byte[] data = dp.getData();
String s = new String(data,0,dp.getLength());
System.out.println("数据是:"+s);
}
//ds.close();
}
//SendDemo.java
package com.itUDP;
import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class SendDemo2 {
public static void main(String[] args) throws IOException {
//构造数据报套接字并将其绑定到本地主机的任何端口
DatagramSocket ds = new DatagramSocket();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
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.1.7"),2001);
ds.send(dp);
}
ds.close();
}
}
}
步骤:
1.创建客户端的Socket对象(Socket)
Socket(String host,int port)
2.获取输出流,写数据
OutputStream getOutputStream()
3.释放资源
void close()
步骤:
1.创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port)
2.监听客户端连接,返回一个Socket对象
Socket accept()
3.获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
4.释放资源
void close()
练习一:
客户端发送数据,接收服务器反馈
服务器接收数据,给出反馈
//ServerDemo.java
package com.itTCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket ss = new ServerSocket(10010);
//侦听要连接的套接字,并接受他
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println("服务器:"+data);
//给出反馈
OutputStream os = s.getOutputStream();
os.write("数据已收到!".getBytes());
//释放资源
s.close();
ss.close();
}
}
//ClientDemo.java
package com.itTCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo1 {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(Socket)
Socket s = new Socket("192.168.1.7",10010);
//获取输出流,写数据
OutputStream os =s.getOutputStream();
os.write("hello,tcp".getBytes());
//接收服务器的反馈
byte[] bys = new byte[1024];
InputStream is = s.getInputStream();
int len = is.read(bys);
String str = new String(bys,0,len);
System.out.println("客户端"+str);
//释放资源
s.close();
}
}
练习2:
客户端:数据来自键盘的输入,直到输入的数据是886,发送数据结束
服务端:接收的数据在控制台输出
ServerDemo2.java
package com.itTCP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo2 {
public static void main(String[] args) throws IOException {
//接收的数据在控制台输出
ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
ss.close();
}
}
//ClientDemo2.java
package com.itTCP;
import java.io.*;
import java.net.Socket;
public class ClientDemo2 {
public static void main(String[] args) throws IOException {
//数据来自键盘的输入,直到输入的数据是886,发送数据结束
Socket s = new Socket("192.168.1.7",10010);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while((line= br.readLine())!=null){
if("886".equals(line)){
break;
}
//获取输出流对象
// OutputStream os = s.getOutputStream();
// os.write(line.getBytes());
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
s.close();
}
}
练习三:
客户端:数据来自键盘的输入,直到输入的数据是886,发送数据结束
服务端:接收到的数据写入文本文件
//ServerDemo3.java
package com.itTCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo3 {
public static void main(String[] args) throws IOException {
//接收到的数据写入文本文件
ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("F://tcp.txt"));
String line;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
ss.close();
}
}
//ClientDemo.java
package com.itTCP;
import java.io.*;
import java.net.Socket;
public class ClientDemo3 {
public static void main(String[] args) throws IOException {
//数据来自键盘的输入,直到输入的数据是886,发送数据结束
Socket s = new Socket("192.168.1.7",10010);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while((line= br.readLine())!=null){
if("886".equals(line)){
break;
}
//获取输出流对象
// OutputStream os = s.getOutputStream();
// os.write(line.getBytes());
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
s.close();
}
}
练习四:
客户端:数据来自文本文件
服务端:接收到的数据写入文本文件
//ServerDemo4.java
package com.itTCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo4 {
public static void main(String[] args) throws IOException {
//接收到的数据写入文本文件
ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("F://tcpwrite.txt"));
String line;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
ss.close();
}
}
//ClientDemo.java
package com.itTCP;
import java.io.*;
import java.net.Socket;
public class ClientDemo4 {
public static void main(String[] args) throws IOException {
//数据来自文本文件
Socket s = new Socket("192.168.1.7",10010);
BufferedReader br = new BufferedReader(new FileReader("F:\\tcp.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()) );
String line;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
br.close();
s.close();
}
}
练习五:
客户端:数据来自文本文件,接收反馈
服务端:接收到的数据写入文本文件,给出反馈
//ServerDemo5.java
package com.itTCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo5 {
public static void main(String[] args) throws IOException {
//接收到的数据写入文本文件
ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("F://tcpwrite.txt"));
String line;
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();
ss.close();
}
}
//ClientDemo.java
package com.itTCP;
import java.io.*;
import java.net.Socket;
public class ClientDemo5 {
public static void main(String[] args) throws IOException {
//数据来自文本文件
Socket s = new Socket("192.168.1.7",10010);
BufferedReader br = new BufferedReader(new FileReader("F:\\tcp.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()) );
String line;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
s.shutdownOutput();
BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
String lline = brClient.readLine();
System.out.println("服务器反馈的数据是:"+lline);
br.close();
s.close();
}
}
出现的问题:程序一直等待
原因:读数据的方式是阻塞式的
解决办法:自定义结束标记,使用shutdownOutput()方法(推荐)
练习六:
客户端:数据来自文本文件,接收反馈
服务端:接收到的数据写入文本文件,给出反馈,代码用线程进行封装,为每一个客户端开启一个线程
ServerThread.java
package com.itTCP;
import java.io.*;
import java.net.Socket;
public class ServerThread implements Runnable {
//接收到的数据写入文本文件,给出反馈,代码用线程进行封装,为每一个客户端开启一个线程
private Socket s;
public ServerThread(Socket s){
this.s = s;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
int count = 0;
File file = new File("F:\\tcp["+count+"].txt");
while(file.exists()){
count++;
file = new File("F:\\tcp["+count+"].txt");
}
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
String line;
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();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//ServerDemo6.java
package com.itTCP;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo6 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10010);
while(true){
Socket s = ss.accept();
new Thread(new ServerThread(s)).start();
}
}
}
//ClientDemo6.java
package com.itTCP;
import java.io.*;
import java.net.Socket;
public class ClientDemo6 {
public static void main(String[] args) throws IOException {
//数据来自文本文件
Socket s = new Socket("192.168.1.7",10010);
BufferedReader br = new BufferedReader(new FileReader("F:\\tcp.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()) );
String line;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
s.shutdownOutput();
BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
String lline = brClient.readLine();
System.out.println("服务器反馈的数据是:"+lline);
br.close();
s.close();
}
}