网络编程概述

网络编程概述:

        计算机网络:

是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议

的管理和协调下,实现资源共享和信息传递的计算机系统。

计算机网络的主要功能:

1:资源共享

2:信息传输与集中处理

3:均衡负荷与分布处理

4:综合信息服务

计算机网络的分类:

局域网(LAN)、城域网(MAN)、广域网(WAN)。Internet可视为世界最大的广域网

网络模型:

OSI参考模型:

计算机网络之间以何种规则进行通信,就是网络模型研究问题。国际标准化组织ISO与1978年提出"开放系统互连参考模型",

即OSI(OpenSystem Interconnection)。OSI参考模型把计算机网络分成物理层、数据链路层、网络层、传输层、会话层、

表示层、应用层。OSI参考模型已成为各种计算机网络结构的参考标准。

TCP/IP协议模型:

按TCP/IP协议模型,网络被分成物理+数据链路、网络层、传输层、应用层。TCP/IP协议模型和OSI参考模型有着大致的对应关系。

    --------------------------

应用层        

    --------

表示层             应用层(HTTP POP3 SMTP FTP TELNET)

    --------

会话层

    --------------------------

传输层     传输层    (TCP UDP)

    --------------------------

网络层     网络层    (IP)

    --------------------------

    数据链路层

   --------    物理+数据链路

物理层

  ----------------------------

   OSI分层模型和TCP/IP分层模型的对应关系

网络通信的三要素:

1:IP地址:

IP地址用于唯一的标识网络中的一个通信实体,

IP地址的分类:

IP地址的分类:

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.254        

172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。

C类:192.0.0.1---223.255.255.254        

192.168.X.X是私有地址

D类:224.0.0.1---239.255.255.254        

E类:240.0.0.1---247.255.255.254        

如何在查看本机的ip地址:打开命令行,输入ipconfig

测试网络连接是否良好:打开命令行,输入ping ip地址

本地回环地址:127.0.0.1

网络地址:xxx.xxx.xxx.0

广播地址:xxx.xxx.xxx.255

案例体现:

import java.io.IOException;

import java.net.InetAddress;

import java.net.UnknownHostException;

/**

 * java提供了InetAddress类来代表IP地址,InetAddress类没用提供构造器,而是通过静态的构造方法来获取InetAddress实例。

 *        1:static InetAddressgetByName(String host):在给定主机名或者ip地址的情况下,获取InetAddress的实例

 *         2:staticInetAddress getLocalHost() 返回本地主机所对应的InetAddress实例

 *        3:staticInetAddress[] getAllByName(String host) 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址

 *InetAddress还提供了获取InetAddress实例对应的IP地址和主机名的方法:

 *        1: StringgetHostAddress() 返回 IP 地址字符串(以文本表现形式)。

 *        2: StringgetHostName()  获取此IP 地址的主机名。

 *        3:StringgetCanonicalHostName()  获取此IP 地址的完全限定域名。

 *        4: booleanisReachable(int timeout) 测试是否可以达到该地址。 

 * */

public class InetAddressTest {

public static void main(String[] args) throws IOException {

//获取本机的InetAddress实例

InetAddress ia1 = InetAddress.getLocalHost();

//获取本机的IP地址

System.out.println("我的IP地址是:"+ ia1.getHostAddress());

//获取本机的主机名

System.out.println("我的主机名是:" + ia1.getHostName());

//通过主机名创建对象

InetAddress ia2 = InetAddress.getByName("113.251.70.43");

System.out.println("该计算机的主机名是:" + ia2.getHostName());

System.out.println("该计算机的ip地址是:" + ia2.getHostAddress());

}

}

2:端口号:

在明确IP地址的情况下,用于表示数据具体交给哪个通信程序处理。

因此,端口号就是应用程序与外界交流的出入口。

端口号的分类:

1:公认端口:从0到1023,它们紧密绑定一些特定的服务

2:注册端口:从1024到49151,应用程序一般使用这个范围内的端口

3:动态或私有端口:从49152到65535,这些端口是应用程序使用的动态端口。

常见的端口:

web服务:80

web服务器:默认是8080

数据库:3306

 

3:传输协议:

常用的TCP协议和UDP协议

UDP协议:是一种面向非连接的协议,不需要建立连接。将数据源和目的封装成数据包中,

每个数据报的大小限制在64k;因无连接,所以是不可靠协议;速度快

   作用:完成网络数据流和数据报之间的转换。在信息的发送端,UDP协议将网络数据流

封装成数据报,然后将数据发送出去;在信息的接收端,UDP协议将数据报转换成

实际的数据内容。

   应用场景:聊天、视频会话、桌面共享等。

TCP协议:建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手

完成连接,是可靠协议;效率会稍低

UDP协议和TCP协议直接位于IP协议之上。IP协议属于网络层协议,UDP协议和TCP协议都属于传输层协议

Socket:

Socket就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket之间的通信,数据在两个Socket之间

通过IO流传输

基于UDP协议的网络编程:

使用DatagramSocket发送、接收数据:

Java使用DatagramSocket代表UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流

它的唯一作用就是接收和发送数据报,Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送

数据都是通过DatagramPacket对象来完成的

DatagramSocket的构造器:

 DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。接收端和发送端均可使用

 DatagramSocket()  构造数据报套接字并将其绑定到本地主机上任何可用的端口。仅用于发送端

 DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址,指定端口

DatagramSocket的方法:

 voidreceive(DatagramPacket p) 接收数据报,该方法会阻塞调用该方法的线程,直到接收到数据为止

 voidsend(DatagramPacket p) 发送数据报

DatagramPacket的构造器:

DatagramPacket(byte[] buf, int length) 先创建一个空数组,用来接收长度为 length 的数据包。接收存储数据

DatagramPacket(byte[] buf, int length, InetAddress address, intport)

构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

DatagramPacket的方法:

 byte[]getData() 返回数据缓冲区。

 InetAddressgetAddress() 返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。

 intgetPort() 返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。

 intgetLength() 返回将要发送或接收到的数据的长度。

案例体现一:

/*

 * Description:

 *   发送端从键盘录入数据,在接收端显示,模拟一个简单的聊天小程序

 */

package com.itheima.sent;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

 

public class SentDemo2 {

public static void main(String[] args) throws IOException {

//1.创建UDPSocket服务对象

DatagramSocket ds = new DatagramSocket(8888);

//2.确定数据,将数据打包

BufferedReader br = new BufferedReader(newInputStreamReader(System.in));

String line = null;

while((line = br.readLine()) != null)

{

//自定义结束标记

if("886".equals(line))

{

break;

}

DatagramPacket dp = new DatagramPacket(line.getBytes(),line.length(), InetAddress.getByName("192.168.1.101"), 10000);

//3.发送数据

ds.send(dp);

}

//4.关闭资源

ds.close();

}

}

package com.itheima.receive;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

public class ReceiveDemo1 {

public static void main(String[] args) throws Exception {

//步骤:

//1.创建UDP的Socket服务

DatagramSocket ds = new DatagramSocket(10000);

while(true){

//2.定义一个空的数据报,因为要接收存储数据,

byte[] bys = new byte[1024];

DatagramPacket dp = new DatagramPacket(bys, bys.length);

//3.通过UDP服务的receive()方法,将数据存入数据包中

ds.receive(dp);

//4.通过数据报的方法,解析数据

String data = new String(dp.getData(), 0, dp.getLength());

System.out.println("ip:" +dp.getAddress().getHostAddress() + "端口号:" + dp.getPort() + "  :" + data);

//5.关闭资源

}

}

}

案例体现二:

/*

对上面程序进行改进,加入多线程

 */

import java.io.IOException;

import java.net.DatagramSocket;

 

import com.itheima.receive.ReceiveThread;

import com.itheima.sent.SentThread;

 

public class ChatRoom {

public static void main(String[] args) throws IOException {

DatagramSocket ds1 = new DatagramSocket();

DatagramSocket ds2 = new DatagramSocket(12306);

 

SentThread st = new SentThread(ds1);

ReceiveThread rt = new ReceiveThread(ds2);

 

st.start();

rt.start();

}

}

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.net.UnknownHostException;

 

public class SentThread extends Thread{

private DatagramSocket ds;

public SentThread(DatagramSocket ds)

{

this.ds = ds;

}

public void run()

{

BufferedReader br = null;

try {

br = new BufferedReader(new InputStreamReader(System.in));

String line = null;

 

while((line = br.readLine()) != null)

{

DatagramPacket dp = new DatagramPacket(line.getBytes(),line.length(), InetAddress.getByName("192.168.1.101"), 12306);

ds.send(dp);

if("886".equals(line))

break;

}

 

 

 

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally

{

try {

br.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

ds.close();

}

}

}

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

 

public class ReceiveThread extends Thread{

private DatagramSocket ds;

public ReceiveThread(DatagramSocket ds)

{

this.ds = ds;

}

public void run()

{

try {

while(true){

byte[] bys = new byte[1024];

DatagramPacket dp = new DatagramPacket(bys, bys.length);

 

ds.receive(dp);

 

String data = new String(dp.getData(), 0, dp.getLength());

System.out.println("ip:" +dp.getAddress().getHostAddress() + "*****" + data);

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

基于TCP协议的网络编程:

使用SeverSocket创建TCP服务器端:

Java中能够接收其他通信实体连接请求的类是ServerSocket,SeverSocket对象用于监听来自客户端的Socket连接,

如果没有连接,它将一直处于等待状态。

SeverSocket的构造方法:

ServerSocket(int port) 创建绑定到特定端口的服务器套接字。

SeverSocket的方法:

 Socketaccept() :如果接收到一个客户端Socket的连接请求,

该方法将返回一个与客户端Socket对应的Socket对象。否则该方法将一直处于等待状态,线程被阻塞。

使用Socket客户端进行通信:

客户端可以使用Socket的构造器来连接到指定的服务器。

Socket的构造方法:

Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

如果没有指定,系统默认使用本地主机的IP地址,默认分配端口

Socket的方法:

InputStream getInputStream() 返回该Socket对象对应的输入流,让程序通过该输入流向Socket读取数据

OutputStream getOutputStream() 返回该Socket对象对应的输出流,让程序通过该流向Socket中写入数据

 voidshutdownOutput() 禁用此套接字的输出流。告诉服务端数据已写完

案例体现一:

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

/*

 *TCP客户端:

 *        通过查阅API文档发现,在Socket对象建立时,就指定连接的主机,

 *        因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端的存在,

 *        并且连接成功后,才能进行数据传输

 *1:建立客户端的Socket服务,并明确要连接的服务器。

 *2:如果连接建立成功,就表明,已经建立了数据传输的通道.

 *        就可以在该通道通过IO进行数据的读取和写入.

 *        该通道称为Socket流,Socket流中既有读取流,也有写入流.

 *3:通过Socket对象的方法,可以获取这两个流

 *4:通过流的对象可以对数据进行传输

 *5:如果传输数据完毕,关闭资源

*/

public class ClientDemo1 {

public static void main(String[] args) throws IOException {

//1:建立客户端的Socket服务,并明确要连接的服务器。

Socket s = new Socket("192.168.1.101", 10001);

//2:向管道写入

PrintWriter pw = new PrintWriter(s.getOutputStream(), true);

 

pw.println("haha,我来了");

BufferedReader br = new BufferedReader(newInputStreamReader(s.getInputStream()));

String line = br.readLine();

System.out.println(line);

//关闭资源

s.close();

}

}

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

/*

TCP服务端:

1:建立服务器端的socket服务,需要一个端口

2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信

3:通过客户端的获取流对象的方法,读取数据或者写入数据

4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的

*/

public class ServerDemo1 {

public static void main(String[] args) throws IOException {

// 建立服务器的Socket对象,指定监听端口

ServerSocket ss = new ServerSocket(10001);

// 返回当前连接的客户端对象

Socket s = ss.accept();

// 获取输入流对象

BufferedReader br = new BufferedReader(newInputStreamReader(s.getInputStream()));

String line = br.readLine();

System.out.println("ip:" +s.getInetAddress().getHostAddress() + "  :" + line);

//获取输出流对象,给客户端反馈

PrintWriter pw = new PrintWriter(s.getOutputStream());

pw.println("哈哈,我走了");

//关闭资源

s.close();

ss.close();

}

}

 

案例体现二:

/*

 * 功能:向服务器并发上传图片

 *        为了让多个客户端同时访问服务端,那么最好就把每一个客户端封装到一个单独的线程

 *        就可以同时处理多个客户端的请求

 * 如何定义线程呢?

 *        只要明确每一个客户端要在服务端执行的代码即可

 * */

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.Socket;

/*

 * 功能:向服务器上传图片

 * 1:服务端点

 * 2:从客户端读取图片

 * 3:通过Socket输出流发送给服务端

 * 4:从服务端获取反馈信息

 * 5:关闭资源

 * */

public class ClientDemo3 {

public static void main(String[] args) throws IOException {

//创建Socket对象

Socket s = new Socket("192.168.1.101", 10011);

//封装数据源

BufferedInputStream bis = new BufferedInputStream(newFileInputStream("K:\\pic.jpg"));

 

//封装目的地

BufferedOutputStream pw = newBufferedOutputStream(s.getOutputStream());

byte[] bys = new byte[1024];

int len = 0;

while((len = bis.read(bys)) != -1)

{

pw.write(bys, 0, len);

pw.flush();

}

//告诉服务端数据已写完

s.shutdownOutput();

BufferedReader br = new BufferedReader(newInputStreamReader(s.getInputStream()));

String line = br.readLine();

System.out.println(line);

bis.close();

s.close();

}

}

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.PrintWriter;

import java.net.Socket;

 

public class PicServerThread implements Runnable{

private Socket s;

public PicServerThread(Socket s)

{

this.s = s;

}

@Override

public void run() {

String ip = s.getInetAddress().getHostAddress();

try {

int count = 1;

System.out.println(ip + "  进来啦");

File file = new File("k:\\" + "pic" + count +".jpg");

while(file.exists()){

file = new File("k:\\" + "pic" + (count++) +".jpg");

}

 

BufferedInputStream br = newBufferedInputStream(s.getInputStream());

BufferedOutputStream pw = new BufferedOutputStream(newFileOutputStream(file));

byte[] bys = new byte[1024];

int len = 0;

while((len = br.read(bys)) != -1)

{

pw.write(bys, 0, len);

pw.flush();

}

PrintWriter pw1 = new PrintWriter(s.getOutputStream());

pw1.println("上传成功");

pw1.flush();

pw.close();

s.close();

} catch (IOException e) {

throw new RuntimeException(ip + "上传失败");

}

}

}

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

 

public class SeverDemo4 {

public static void main(String[] args) throws IOException {

ServerSocket ss = new ServerSocket(10011);

while(true)

{

Socket s = ss.accept();

new Thread(new PicServerThread(s)).start();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值