Java 网络编程(上)

------- android培训java培训、期待与您交流! ----------

 网络编程(上)

一、网络编程

1 网络模型
OSI 参考模型
TCP/IP 参考模型
 
2网络通讯要素IP 地址
端口号

传输协议

二、网络参考模型

 

三、网络通讯要素

IP地址:    InetAddress
网络中设备的标识
不易记忆,可用主机名
本地回环地址: 127.0.0.1  主机名: localhost


端口号用于标识进程的逻辑地址,不同进程的标识有效端口:0~65535,其中0~1024系统使用或保留端口。

 传输协议通讯的规则常见协议:TCPUDP

四、TCPUDP 【重要】

1 UDP
将数据及源和目的封装成数据包中, 不需要建立连接
每个数据报的大小在限制在 64k
因无连接,是不可靠协议
不需要建立连接,速度快
 
2、TCP
建立连接 ,形成传输数据的通道。
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低

 

五、Socket

1、有关 Socket
1 Socket 就是为网络服务提供的一种机制。
2 通信的两端都有 Socket
3 网络通信其实就是 Socket 间的通信。
4 数据在两个 Socket 间通过 IO 传输。
注意: Socket 可以理解为码头,有码头才有船可以对货(数据)进行装卸(读写)。
但是由于船运输的方式不同,所以有了不同的服务方式。
一个是 UDP ,另外一个是 TCP
 
2
、重要的类
1)public class DatagramSocket
extends  Object
此类表示用来发送和接收数据报包的套接字。
2)public final class DatagramPacket
extends  Object
此类表示数据报包。
3) public class InetAddress
extends  Object
implements  Serializable
此类表示互联网协议 (IP) 地址。
3、小知识
192.168.1.254
192.168.1.0     这是这个段里边的网络地址
192.168.1.255    这是 192.168.1 这个段里边的广播地址
 
3 Socket 编程
1 )示例:
需求:通过 udp 传输方式,将一段文字数据发送出去。,
定义一个 udp 发送端。
思路:
1,建立updsocket服务。
2,提供数据,并将数据封装到数据包中。
3,通过socket服务的发送功能,将数据包发出去。
4 ,关闭资源
 
import java.net.*;
class  UdpSend
{
public static void main(String[] args) throws Exception
{
//1 ,创建 udp 服务。通过 DatagramSocket 对象。
DatagramSocket ds = new DatagramSocket(8888);  // 发送端可以使用默认端口。。。
 
//2 ,确定数据,并封装成数据包。 DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
 
byte[] buf = "udp ge men lai le ".getBytes();
DatagramPacket dp = 
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),10000);
 
//3 ,通过 socket 服务,将已有的数据包发送出去。通过 send 方法。
ds.send(dp);
 
//4 ,关闭资源。
 
ds.close();
 
}
}
 
/*
需求:
定义一个应用程序,用于接收 udp 协议传输的数据并处理的。
定义 udp 的接收端。
思路:
1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识。
方便于明确哪些数据过来该应用程序可以处理。
 
2,定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
5
,关闭资源。
 
*/
class  UdpRece
{
public static void main(String[] args) throws Exception
{
//1, 创建 udp socket ,建立端点。
DatagramSocket ds = new DatagramSocket(10000);
while(true)
{
//2, 定义数据包。用于存储数据。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
 
//3 ,通过服务的 receive 方法将收到数据存入数据包中。
ds.receive(dp);// 阻塞式方法。
 
//4 ,通过数据包的方法获取其中的数据。
String ip = dp.getAddress().getHostAddress();
 
String data = new String(dp.getData(),0,dp.getLength());
 
int port = dp.getPort();
 
System.out.println(ip+"::"+data+"::"+port);
 
}
//5 ,关闭资源
//ds.close();  // 第二部来的 ,互动 使接收端一直开着。。
 
}
}
 
2) 示例----------------必须掌握!!!
编写一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
 
因为收和发动作是不一致的,所以要定义两个 run 方法。
而且这两个方法要封装到不同的类中。
import java.io.*;
import java.net.*;
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
 
String line = null;
 
while((line=bufr.readLine())!=null)
{
 
byte[] buf = line.getBytes();
 
DatagramPacket dp = 
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10002);
 
ds.send(dp);
 
if("886".equals(line))
break;
}
}
catch (Exception e)
{
throw new RuntimeException(" 发送端失败 ");
}
}
}
 
class Rece implements Runnable
{
 
private DatagramSocket ds;
public Rece(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
 
ds.receive(dp);
 
 
String ip = dp.getAddress().getHostAddress();
 
String data = new String(dp.getData(),0,dp.getLength());
 
if("886".equals(data))
{
System.out.println(ip+".... 离开聊天室 ");
break;
}
 
 
System.out.println(ip+":"+data);
}
}
catch (Exception e)
{
throw new RuntimeException(" 接收端失败 ");
}
}
}
 
 
class  ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10002);
 
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
 
}
}
 
3) 示例
/*
演示 tcp 传输。
 
1,tcp 分客户端和服务端。
2 ,客户端对应的对象是 Socket
服务端对应的对象是 ServerSocket
 
客户端,
通过查阅 socket 对象,发现在该对象建立时,就可以去连接指定主机。
因为 tcp 是面向连接的。所以在建立 socket 服务时,
就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
 
需求:给服务端发送给一个文本数据。
 
步骤:
1 ,创建 Socket 服务。并指定要连接的主机和端口。
 
*/
import java.io.*;
import java.net.*;
class  TcpClient
{
public static void main(String[] args) throws Exception 
{
// 创建客户端的 socket 服务。指定目的主机和端口
Socket s = new Socket("192.168.1.254",10003);
// 为了发送数据,应该获取 socket 流中的输出流。
OutputStream out = s.getOutputStream();
 
out.write("tcp ge men lai le ".getBytes());
 
 
s.close(); // 流就不用关了,因为是随着 socket 来的
}
}
 
 
/*
需求:定义端点接收数据并打印在控制台上。
 
服务端 :
1 ,建立服务端的 socket 服务。 ServerSocket();
并监听一个端口。
2 ,获取连接过来的客户端对象。
通过 ServerSokcet 的  accept 方法。没有连接就会等,所以这个方法阻塞式的。
3 ,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。
并打印在控制台。
 
4 ,关闭服务端。(可选)
*/
class  TcpServer
{
public static void main(String[] args) throws Exception
{
// 建立服务端 socket 服务。并监听一个端口。
ServerSocket ss = new ServerSocket(10003);
 
// 通过 accept 方法获取连接过来的客户端对象。
while(true)
{
Socket s = ss.accept();
 
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");
 
// 获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
 
System.out.println(new String(buf,0,len));
 
s.close();// 关闭客户端 .
}
//ss.close();
}
}
 
4 )、示例
 
需求:建立一个文本转换服务器。
客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。
而且客户度可以不断的进行文本转换。当客户端输入 over 时,转换结束。
 
分析:
客户端:
既然是操作设备上的数据,那么就可以使用 io 技术,并按照 io 的操作规律来思考。
源:键盘录入。
目的:网络设备,网络输出流。
而且操作的是文本数据。可以选择字符流。
 
步骤
1,建立服务。
2,获取键盘录入。
3,将数据发给服务端。
4,后去服务端返回的大写数据。
5 ,结束,关资源。
 
都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。
 
 
*/
import java.io.*;
import java.net.*;
 
class  TransClient
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("192.168.1.254",10005);
 
 
// 定义读取键盘数据的流对象。
BufferedReader bufr = 
new BufferedReader(new InputStreamReader(System.in));
 
 
// 定义目的,将数据写入到 socket 输出流。发给服务端。
//BufferedWriter bufOut = 
//new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
 
// 定义一个 socket 读取流,读取服务端返回的大写信息。
BufferedReader bufIn = 
new BufferedReader(new InputStreamReader(s.getInputStream()));
 
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line);
// bufOut.write(line);
// bufOut.newLine();
// bufOut.flush();
 
String str =bufIn.readLine();
System.out.println("server:"+str);
}
 
bufr.close();
s.close();
 
 
}
}
/*
 
服务端:
源: socket 读取流。
目的: socket 输出流。
都是文本,装饰。
 
*/
 
class  TransServer
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10005);
 
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"....connected");
 
// 读取 socket 读取流中的数据。
BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream()));
 
// 目的。 socket 输出流。将大写数据写入到 socket 输出流,并发送给客户端。
//BufferedWriter bufOut = 
//new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
 
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
 
String line = null;
while((line=bufIn.readLine())!=null)
{
 
System.out.println(line);
out.println(line.toUpperCase());
}
 
s.close();
ss.close();
 
}
}
/*
该例子出现的问题。
现象:客户端和服务端都在莫名的等待。
为什么呢?
因为客户端和服务端都有阻塞式方法。这些方法么没有读到结束标记。那么就一直等
而导致两端,都在等待。
 
((line=bufIn.readLine())!=null)
 
readLine 方法是阻塞式方法,必须碰到回车符才会判断读取一行完毕,返回数据,否则会一直在读
所以加 bu fOut.newLine();---- 》自动换行
 
*/
 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值