网络编程
概述:
(1)网络模型
OSI参考模型
TCP/IP参考模型
(2)网络通讯要素
IP地址
端口号
传输协议
(3)网络通讯前提:
找到对方IP数据要发送到指定端口。为了标示不同的应用程序,所以给这些网络应用程序都用数字进行标示。
这个表示就叫端口。
定义通信规则。这个规则称为通信协议,国际组织定义了通用协议TCP/IP
网络通讯要素:
IP地址:InetAddress
网络中设备的标识
不易记忆,可用主机名
本地回环地址:127.0.0.1
主机名:localhost
端口号
用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口。
传输协议
通讯的规则
常见协议:TCP,UDP
UDP:将数据及源和目的封装成数据包中,不需要建立连接
每个数据报的大小在限制在64k内
因无连接,是不可靠协议
不需要建立连接,速度快
TCP:建立连接,形成传输数据的通道。
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低
三次握手:
第一次:我问你在么?
第二次:你回答在。
第三次:我反馈我知道你在。
UDP传输:
需求:通过udp传输方法,将一段文字数据发送出去;
思路:
1,建立DatagramSocket服务。
2,提供数据,并将数据封装到数据包中。
3,通过socket服务的发送功能,将数据包发出去。
4,关闭资源。
发送端:
class UDPSend{
public staticvoid main(String[] args) throws Exception{
DatagramSocketds = new DatagramSocket();
byte[] buf ="这是UDP发送端".getBytes();
DatagramPacketdp = newDatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10000);
ds.send(dp);
ds.close();
}
}
接收端:
class UDPRece{
public staticvoid main(String[] args) throws Exception{
DatagramSocketds = new DatagramSocket(10000);
byte[] buf =new byte[1024];
DatagramPacketdp = new DatagramPacket(buf,buf.length);
ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
String ip =dp.getAddress().getHosyAddress();//获取发送端的ip
String data= new String(dp.getData(),0,dp.getLength());//获取数据
int port =dp.getPort();//获取发送端的端口号
sop(ip+":"+data+":"+port);
ds.close();
}
}
//*编写一个聊天程序*//
分析:有收数据的部分和发数据的部分。这两部分同时执行。那就需要使用到多现程技术。
一个线程控制收,一个线程控制发。因为收和发动作是不一致的,
所以要定义两个run方法。而且这两个方法要封装不同的类中。
发送端:
class UDPSendimplements Runnable{
privateDatagramSocket ds;
publicUDPSend(){}
publicUDPSend(DatagramSocket ds){
this.ds=ds;
}
public voidrun(){
try{
BufferedReaderbufr = new BufferedReader(new InputStreamReader(System.in));
Stringline = null;
while((line= bufr.readLine())!=null){
if("886".equals(line))
break;
byte[]buff = line.getBytes();
DatagramPacket dp = newDatagramPacket(
buf,buf.length,InetAddress.getByName("127.0.0.1"),10000);
ds.send(dp);
}
}
catch(Exceptione){
thrownew RuntimeException("发送失败");
}
}
}
接收端:
class UDPReceimplements Runnable{
private DatagramSocket ds;
publicUDPSend(){}
publicUDPSend(DatagramSocket ds){
this.ds=ds;
}
public voidrun(){
try{
while(true){
byte[]buf = new byte[1024];
DatagramPacketdp = new DatagramPacket(buf,buf.length);
ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
Stringip = dp.getAddress().getHosyAddress();//获取发送端的ip
Stringdata = new String(dp.getData(),0,dp.getLength());//获取数据
intport = dp.getPort();//获取发送端的端口号
sop(ip+":"+data+":"+port);
}
}
catch(Exceptione){
throw new RuntimeException("接收失败");
}
}
}
测试类:
class UDPTest{
public staticvoid main(String[] args){
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = newDatagramSocket(10000);
new Thread(new UDPSend(sendSocket)).start();
newThread(new UDPRece(receSocket)).start();
}
}
TCP传输:
Socket和ServerSocket建立客户端和服务端。
客户端:通过查阅socket对象,发现在该对象建立时,就可以去连接制定主机。因为tcp是面向对象的,所以在建立socket服务时,就要有服务端存在,并连接成功、形成通路之后,在该通道进行数据的传输。
TCP传输流程:
客户端:
1、建立Socket服务,并制定要连接的主机和端口;
2、获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端;
3、获取Socket流中的输出流InputStream,获取服务端的反馈信息;
4、关闭资源。
服务端:
1、建立ServerSocket服务,并监听一个端口;
2、获取连接过来的客户端对象。通过ServerSocket的accept方法。没有连接就会等,所以这个方法是阻塞式的;
3、使用客户端对象的读取流获取客户端发送过来的数据;
4、通过客户端对象的写入流反馈信息给客户端;
5、关闭资源;
练习代码1:建立一个文本转换服务端,客户给服务端发送文本,服务端将数据转换成大写后返回给客户端,当客户端输入over时,转换结束
//客户端:
class TCPClient{
public staticvoid main(String[] args){
Socket s =new Socket("127.0.0.1",10000);
BufferedReaderbufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriterbufOut = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
BufferedReaderbufIn = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line= null;
while((line= bufr.readLine())!=null){
if("over".equals(line))
break;
bufOut.write(line);
bufOut.newLine();
bufOut.flush();
StringretVal = bufIn.readLine();
sop("server:"+retVal);
}
bufr.close();
s.close();
}
}
//服务端:
class TCPServer{
public staticvoid main(String[] args){
ServerSocketss = new ServerSocket(10000);
Socket s =ss.accept();
String ip =s.getInetAddress().getHostAddress();
sop(ip);
BufferedReaderbufIn = new BufferedReader(new InputStreamReader(
s.getInputStream()));
BufferedWriterbufOut = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
while((line = bufIn.readLine())!=null){
bufOut.write(line.toUpperCase());
bufOut.newLine();
bufOut.flush();
}
s.close();
ss.close();
}
}