------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
网络编程
网络间的通信方式分为两种,一种是面向无连接(UDP),一种是面向连接(TCP)。而网络间的通信底层都遵循一种通信机制,也叫Socket,我把它理解为是一种端口,因为每个应用程序运行都有指定的端口进行数据的传输。所以在用前面的两种通信方式时都要指定相同的端口。
UDP的特点:将数据及源和目的封装到数据包中,不需要建立连接;每个数据包的大小限制在64K内,如果数据包大于64K就会自动的将其分割成小的包;因为是无连接,所以是不可靠协议,但是传输速度相对较快。
TCP的特点:需建立连接,形成传输数据的通道,并通过三次握手来确定通道的安全,因此传输效率稍低。
网络模型
网络传输的过程:通过把数据进行封包然后传到另外一个主机,另外一个主机进行数据拆包。
有关网路编程的类
有关IP的类----------àInetAddress(java.net包中)
InetAddress ip = InetAddress.getLocalHost(); //获取的主机名和地址
Ip.getHostAddress(); //获取主机Ip
Ip.getHostName(); //获取主机名
Ip.getByName(String name); //获取其他的主机
UDP传输的操作步骤:
发送端:
1、建立UDP的socket服务,创建对象时如果没有明确端口,系统会自动分配一个未被使用的端口;
2、明确要发送的具体数据;
3、将数据封装成了数据包;
4、用socket服务的send方法将数据包发送出去;
5、关闭资源。
class UdpSend{
public static voidmain(String[] args)throws Exception {
DatagramSocket ds = newDatagramSocket();//指定发送端口,不指定系统会随机分配。
//因为底层传输的是字节流,所以要把传送的内容变成字节数组再进行传输。
byte[] buf = "UDP wo lai le".getBytes();
//创建一个数据包对象,DatagramPacket(byte[] buf, int length,InetAddress address, int port)
//buf - 包数据。length - 包长度,address - 目的地址。port - 目的端口号。
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
ds.send(dp);
ds.close();
}
}
UDP的接收端:
1、创建udp的socket服务,必须要明确一个端口,作用在于,只有发送到这个端口的数据才是这个接收端可以处理的数据;
2、定义数据包,用于存储接收到数据;
3、通过socket服务的接收方法将收到的数据存储到数据包中;
4、通过数据包的方法获取数据包中的具体数据内容,比如ip、端口、数据等等;
5、关闭资源。
lass UdpRece {
public static voidmain(String[] args) throws Exception{
DatagramSocket ds = newDatagramSocket(10000);
byte[] buf = new byte[1024];
DatagramPacket dp = newDatagramPacket(buf,buf.length);
ds.receive(dp);//该方法是阻塞式方法。
String ip =dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = newString(dp.getData(),0,dp.getLength());//将字节数组中的有效部分转成字符串。
System.out.println(ip+":"+port+"--"+text);
ds.close();
}
}
TCP传输的操作步骤:
客户端:
1、建立tcp的socket服务,最好明确具体的地址和端口。这个对象在创建时,就已经可以对指定ip和端口进行连接(三次握手);
2、如果连接成功,就意味着通道建立了,socket流就已经产生了。只要获取到socket流中的读取流和写入流即可,只要通过getInputStream和getOutputStream就可以获取两个流对象;
3、关闭资源。
class TcpClient{
public static voidmain(String[] args) throws Exception{
Socket s = newSocket("192.168.1.100",10002);
OutputStream out = s.getOutputStream();//获取了socket流中的输出流对象。
out.write("tcp,哥们又来了!".getBytes());
s.close();
}
}
服务端:
1、创建服务端socket服务,并监听一个端口;
2、服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象。服务器可以连接多个客户端而能保证数据不会发错的原因就是,它用的是客户端的Socket流;
3、可以通过获取到的socket对象中的socket流和具体的客户端进行通讯;
4、如果通讯结束,关闭资源。注意:要先关客户端,再关服务端。
class TcpServer{
public static voidmain(String[] args) throws Exception{
ServerSocket ss = newServerSocket(10002);//建立服务端的socket服务
Socket s = ss.accept();//获取客户端对象
String ip =s.getInetAddress().getHostAddress();//获取连接进来的客户端的IP地址
System.out.println(ip+".....connected");
//可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。
InputStream in = s.getInputStream();//读取客户端的数据,使用客户端对象的socket读取流
//将获取的数据存放到一个字节数组中,有利于提高效率
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf,0,len);
System.out.println(text);
// 如果通讯结束,关闭资源。
s.close();
ss.close();
}
}
练习:客户端从键盘录入中获取到的字符上传给服务端,服务端收到后再将其转换成大写反馈给客户端。
public class Tcp {
//获取键盘录入,并将其传给服务端,服务接收到数据后再将其转换成大写返回给客户端。
public static void main(String[] args) throws Exception{
//TODO Auto-generated method stub
Socket s=new Socket("192.168.1.100",10003);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
BufferedReader bfr=new BufferedReader(new InputStreamReader(s.getInputStream());
//byte[]buf=new byte[1024];
String line=null;
while((line=br.readLine())!=null)
{
if("over".equals(line))
break;
pw.println(line);
String str=bfr.readLine();
System.out.println(str);
}
br.close();
s.close();
}
}
public class TcpServer {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
ServerSocket ss=new ServerSocket(10003);
Socket s=ss.accept();
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
String line=null;
while((line=br.readLine())!=null)
{
String str=line.toUpperCase();
pw.println(str);
}
br.close();
ss.close();
}
}
总结:在网络编程中一定要注意它的步骤,要明确每一个流程是怎么走的。就以上面这个键盘录入为例分析:
客户端:1、建立连接;
2、键盘录入,再将获取到的数据通过输出流发送到服务端;
3、要获取服务端反馈过来的信息,所以要有一个输入流来接收服务端发来的数据;
4、如果输出流用到了缓冲技术一定要每输完一行就要换行一次,并且刷新一次;
5、当读到有结束标记的语句时就停止读写的操作;
6、关闭资源。
服务端:1、建立连接;
2、通过accept()的方法获取客户端的Socket。并通过它来获取客户端传过来的数据;
3、每获取一行的数据,将其转换成大写再反馈给客户端,直至客户端结束传入数据;
4、关闭资源。