网络工作模式
- 专用服务器结构(Server-Based),简称BS 例如使用浏览器浏览网页
- 客户机/服务器模式(Client/Server,简称C/S结构)
- 对等式网络:(Peer-to-Peer) P2P 点对点 下载 电驴下载
TCP和UDP区别
InetAddress类
public class IPTest {
public static void main(String[] args) {
try {
InetAddress address=InetAddress.getLocalHost();
System.out.println(address);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
TCP/IP协议
- TCP协议 面向连接的、可靠的协议 类似打电话
- TCP协议必须要双方都是监视的同一端口号,然后获取Socket对象的输入输出流,既可以完成互相之间的通讯。
- 只要是隶属同一个局域网,就可以用此协议进行通讯,局域网通讯雏形
- 运行时,先启动服务器端,再启动客户端
- 服务器端
public class Server {
public static void main(String[] args) {
Socket s;
try {
ServerSocket ss=new ServerSocket(8080);
System.out.println("服务器启动");
s=ss.accept();
System.out.println("成功建立连接");
sendMessage(s);
receiveMessage(s);
} catch (IOException e) {
System.out.println("一个客户端下线了");
}
}
private static void receiveMessage(Socket s){
BufferedReader br;
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while (true) {
System.out.println("客户端:"+br.readLine());
}
} catch (IOException e) {
System.out.println("客户端已下线,连接已中断!!!");
}
}
private static void sendMessage(final Socket s) {
new Thread(new Runnable() {
Scanner scanner=new Scanner(System.in);
PrintWriter pw;
public void run() {
try {
pw=new PrintWriter(s.getOutputStream());
while (true) {
System.out.println("请输入服务器要发送的消息:");
pw.println(scanner.next());
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
public class Client {
public static void main(String[] args) {
try {
InetAddress address=InetAddress.getLocalHost();
String str=address.getHostAddress();
Socket s=new Socket(str,8080);
System.out.println("建立连接");
sendMessage(s);
receiveMessage(s);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void sendMessage(final Socket s){
new Thread(new Runnable() {
public void run() {
PrintWriter pw;
Scanner scanner=new Scanner(System.in);
String str;
try {
pw=new PrintWriter(s.getOutputStream());
while (true) {
System.out.println("请输入客户端要发送的信息:");
pw.println(scanner.next());
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private static void receiveMessage(Socket s){
BufferedReader br;
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while (true) {
System.out.println("服务器端:"+br.readLine());
}
} catch (IOException e) {
System.out.println("服务器已下线,连接中断!!!");
}
}
}
UDP协议
- UDP协议 无连接、不可靠的协议,发送包 类似发短信
- Datagrampacket包的概念,UDP协议是发送一个个数据包来传递数据的
- 用来发送消息的Datagramsocket对象不必要指定端口号,因为在那个端口发送都无所谓,只要数据包中包含要接收该数据的IP和端口号就OK了
- 用来接收的Datagramsocket的对象就一定要指定接收数据的端口号,到指定的端口接收该数据包
- UDP协议先启动那个端口都可以,因为是不可靠的连接,发送数据时,不一定接收端在线。
- 服务器端
public class DatagramServser {
public static void main(String[] args) {
try {
DatagramSocket socket = new DatagramSocket(8080);
System.out.println("服务器启动成功,等待接受数据");
receiveMessage(socket);
sendMessage(socket);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void receiveMessage(final DatagramSocket socket)
throws IOException {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
byte[] data = new byte[64 * 1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
System.out.println("客户端:" + new String(data,0,packet.getLength()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
private static void sendMessage(final DatagramSocket socket)
throws UnknownHostException, IOException {
final Scanner scanner = new Scanner(System.in);
final InetAddress address = InetAddress.getByAddress(new byte[] {
(byte) 172, 6, 1, (byte) 144 });
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("请输入要发送的信息:");
try {
final byte[] data;
data = scanner.next().getBytes();
DatagramPacket packet = new DatagramPacket(data,data.length, address, 8090);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
public class DatagramClient {
public static void main(String[] args) {
DatagramSocket socket;
try {
socket = new DatagramSocket(8090);
System.out.println("客户端启动成功");
sendMessage(socket);
receiveMessage(socket);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void receiveMessage(final DatagramSocket socket)
throws IOException {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
byte[] data=new byte[64*1024];
DatagramPacket packet=new DatagramPacket(data, data.length);
socket.receive(packet);
System.out.println("服务器端:"+new String(data,0,packet.getLength()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
private static void sendMessage(final DatagramSocket socket)
throws UnknownHostException, IOException {
final Scanner scanner=new Scanner(System.in);
final InetAddress address=InetAddress.getByAddress(new byte[]{(byte) 172,6,1,(byte) 144});
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("请输入要发送的信息:");
try {
byte[] data=scanner.nextLine().getBytes();
DatagramPacket packet=new DatagramPacket(data, data.length,address,8080);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
URL
- 统一资源定位器,表示Internet上某一资源的地址,定位互联网上的资源。
- 组成:协议名+资源名
通过URL下载网络上的文件
public class Test2 {
public static void main(String[] args) {
try {
File file=new File("D://路飞.jpeg");
if (!file.exists()) {
file.createNewFile();
}
URL url=new URL("http://img4.duitang.com/uploads/item/201511/21/20151121084015_fLaFU.jpeg");
URLConnection connection=url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
InputStream is=connection.getInputStream();
DataInputStream dis=new DataInputStream(is);
DataOutputStream dos=new DataOutputStream(new FileOutputStream(file));
byte[] b=new byte[1024];
int index=dis.read(b);
while (index!=-1) {
dos.write(b, 0, index);
index=dis.read(b);
}
dos.flush();
dos.close();
dis.close();
is.close();
System.out.println("图片读取完毕");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
通过URL实现多线程下载
public class DownLoadUtils {
public static void download(String urls, String path) {
download(urls, path, 3);
}
public static void download(String urls, String path, int threadNum) {
try {
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
URL url = new URL(urls);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
int fileLength = conn.getContentLength();
System.out.println("文件总长度:" + fileLength);
int partLength = fileLength / threadNum;
ArrayList<MyThread> list = new ArrayList<MyThread>();
for (int i = 0; i < threadNum; i++) {
if (i == threadNum - 1) {
MyThread myThread = new MyThread(url, file, i * partLength,
fileLength - i * partLength);
list.add(myThread);
myThread.start();
} else {
MyThread myThread = new MyThread(url, file, i * partLength,
partLength);
list.add(myThread);
myThread.start();
}
}
new ProgressThread(list, fileLength).start();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
private URL url;
private int sum;
private File file;
private int start;
private int length;
public MyThread(URL url, File file, int start, int length) {
this.url = url;
this.file = file;
this.start = start;
this.length = length;
}
public int getLength() {
return sum;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"开始位置:"+start+" 结束位置:"+(start+length)
+" 要下载的长度:"+length);
InputStream is = url.openConnection().getInputStream();
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
is.skip(start);
accessFile.seek(start);
byte[] b = new byte[1024];
int index = is.read(b);
while (index != -1) {
sum += index;
if (sum +1024>length) {
accessFile.write(b, 0, index);
index = is.read(b,0,length-sum);
accessFile.write(b,0,length-sum);
sum=length;
break;
} else {
accessFile.write(b, 0, index);
index=is.read(b);
}
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
accessFile.close();
is.close();
System.out.println(Thread.currentThread().getName() + "子线程下载完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ProgressThread extends Thread{
private ArrayList<MyThread> list;
private int fileLength;
private int sum;
private boolean flag=true;
public ProgressThread(ArrayList<MyThread> list, int fileLength) {
this.list = list;
this.fileLength = fileLength;
}
@Override
public void run() {
while (flag) {
sum=0;
for (MyThread myThread : list) {
sum+=myThread.getLength();
}
int num=(int) (sum*1.0/fileLength*1000);
double persent=num/10.0;
System.out.println("已经下载:"+persent+"%");
if (persent==100) {
System.out.println("下载完成");
break;
}
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
String urls="http://img4.duitang.com/uploads/item/201511/21/20151121084015_fLaFU.jpeg";
String path="D://wulallalal.jpg";
DownLoadUtils.download(urls, path,8);
}
}
封装的理念
- 要学习着将自己写的代码进行封装,以使其更便于自己或者他人使用,将自己写的代码封装成一个工具类,仅将必要的参数传递进去,这样更有益于代码的重复使用,这样也更有利于其他人的使用,类似与黑盒子,使其他人不必知道其实现过程,只需要将必要的参数传递过去,就也能实现代码的复用。