基于Socket的Java网络编程

来源:互联网 发布:mac复制粘贴图片 编辑:程序博客网 时间:2024/05/21 17:47

------- java学习型技术博客、期待与您交流 ----------

Java基础总结之基于Socket的Java网络编程

 

一、网络基础知识

       在学习网络编程之前,需要了解一些网络知识,比如说网络模型,IP地址,通讯端口,通讯协议,其中要重点熟悉TCPUDP通讯协议。

1,网络参考模型

2IP地址

      所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址,它是网络中设备的标识。但由于数字不易记忆,可用主机名。

3,端口

      端口(port)可以认为是计算机与外界通讯交流的出口。用于标识进程的逻辑地址,不同进程的标识。

4,传输协议UDP TCP(必须熟悉)

TCP(传输控制协议)

     TCPTranfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。其特点如下:

◆  建立连接,形成传输数据的通道。

◆  在连接中进行大数据量传输

◆  通过三次握手完成连接,是可靠协议

◆  因为必须建立连接,效率会稍低

UDP(用户数据报协议)

     UDPUser Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。其特点如下:

◆   将数据及源和目的封装成数据包中,不需要建立连接

◆   每个数据报的大小在限制在64k

◆   因没有建立连接,是不可靠协议

◆  也是因为不需要建立连接,所以速度较快

两者应用分析:

      1TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP高。

      2UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。

 

二、基于SocketJava网络编程

1,什么是Socket

       网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket通过网络进行通信的两端都有Socket,网络通信其实就是Socket之间的通信,也就是数据在两个Socket之间通过IO传输。

       由于传输协议的不同,每个传输协议都有自己建立端点的方式,分别对UDP传输和TCP传输进行演示。

UDP传输

UDP传输需要以下几个步骤:

---->建立发送端,接收端。

---->建立数据包。

----> 调用Socket的发送接收方法(send(); receive();)。

----> 关闭Socket

其中,发送端和接受端是两个独立的应用程序,在发送端,要在数据包对象中明确目的地IP及端口。在接收端,要指定监听的端口

UDP传输示例:

需求:编写一个发送端程序,实现通过udp传输方式,将一段文字数据发送出去。用另一个接收端程序接受UDP协议传输的数据。

发送端:

class  UdpSend{public static void main(String[] args) throws Exception{//1,通过DatagramSocket对象创建udp服务,并指定端口。DatagramSocket ds = new DatagramSocket(8888);//2,确定数据,并封装成数据包。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();}}

 

接收端:

class  UdpRece{public static void main(String[] args) throws Exception{//1,创建udp socket,建立端点。DatagramSocket ds = new DatagramSocket(10000);//2,定义数据包。用于存储数据。byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);//3,通过服务的receive方法将收到数据存入数据包中。ds.receive(dp);//阻塞式方法。//获取IP地址String ip = dp.getAddress().getHostAddress();  //4,通过数据包的方法获取其中的数据。String data = new String(dp.getData(),0,dp.getLength());//获取端口int port = dp.getPort();  //打印数据信息System.out.println(ip+"::"+data+"::"+port);  //5,关闭资源ds.close();}}

 

UDP练习:

需求:编写一个聊天程序。分为接收端和发送端,两端需要同时执行,所以需要运用多线程。一个线程负责发送数据,一个线程负责接收数据。由于收发的动作不一致,所以要定义两个run方法,且这两个方法要封装到不同的类中。代码如下:

import java.io.*;import java.net.*;//定义一个发送端Send类实现Runnable接口class Send implements Runnable{//为了DatagramSocket作用于整个类中,创建一个静态成员变量private DatagramSocket ds;//以DatagramSocket对象为参数的构造函数public Send(DatagramSocket ds){this.ds = ds;}//覆盖Runnable接口的run方法public void run(){try{//由系统标准输入设备构造BufferedReader对象,读取键盘录入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.0.104"),10002);//通过DatagramSocket对象的send方法将读取到的数据发送出去。ds.send(dp);//如果输入886则结束if("886".equals(line))break;}}catch (Exception e){throw new RuntimeException("发送端失败");}}}//定义一个接受端Send类实现Runnable接口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);//获取发送端IP地址String ip = dp.getAddress().getHostAddress();//获取发送端发送的数据String data = new String(dp.getData(),0,dp.getLength());//如果接受到的数据为"886"表面客户端离开,打印提示if("886".equals(data)){System.out.println(ip+"....离开聊天室");break;}//打印发送端Ip和数据System.out.println(ip+":"+data);}}catch (Exception e){throw new RuntimeException("接收端失败");}}}class  ChatDemo{public static void main(String[] args) throws Exception{//创建发送端和接受端的Socket对象,(接收端要指定监听的端口)DatagramSocket sendSocket = new DatagramSocket();DatagramSocket receSocket = new DatagramSocket(10002);//创建线程对象并开启new Thread(new Send(sendSocket)).start();new Thread(new Rece(receSocket)).start();}}

 

TCP传输

       UDP 传输分为发送端和接受端,而TCP传输则分为客户端和服务端,分别对应两个对象,SocketServerSocket

◆   客户端:

       Socket对象在建立时,就可以去连接指定主机。因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

◆ 服务端:

    Server端监听某个端口是否有连接请求,Client端向Server 端发出连接请求,Server端向Client端发回接受消息。一个连接就建立起来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。

TCP传输示例

需求:编写一个客户端程序,实现通过tcp传输方式,将一段文字数据发送出去。用另一个服务端程序接受tcp协议传输的数据。

客户端步骤:

     1,创建Socket服务。并指定要连接的主机和端口。

     2,由Socket对象得到输出流,并通过输出流的write方法写出数据

     3,关闭客户端

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对象得到输出流,并通过输出流的write方法写出数据OutputStream out = s.getOutputStream();out.write("This Message from tcpClient".getBytes());s.close();}}

 

服务端步骤:

     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();//获取客户端的IP地址String ip = s.getInetAddress().getHostAddress();System.out.println(ip+".....connected");//获取客户端发送过来的数据,由Socket对象得到输入流。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();}}

 

TCP练习:

需求:模拟一个用户登录,客户端通过键盘录入用户名,服务端对这个用户名进行校验。

           如果该用户存在,在服务端显示xxx,已登陆。并在客户端显示 xxx,欢迎光临。

           如果该用户不存在,在服务端显示xxx,尝试登陆。并在客户端显示 xxx,该用户不存在。

           最多登录三次。

import java.io.*;import java.net.*;//客户端class  LoginClient{public static void main(String[] args) throws Exception{//创建Socket服务。并指定要连接的主机和端口。Socket s = new Socket("192.168.1.254",10008);//构造BufferedReader对象获取键盘录入BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//由Socket对象得到输出流,并构造PrintWriter对象PrintWriter out = new PrintWriter(s.getOutputStream(),true);//由Socket对象得到输入流,并构造相应的BufferedReader对象BufferedReader bufIn =new BufferedReader(new InputStreamReader(s.getInputStream()));//通过for循环限定次数for(int x=0; x<3; x++){//读取键盘录入信息String line = bufr.readLine();//如果客户端录入为空,例如“ctrl+c”退出。则结束循环if(line==null)break;out.println(line);//读取服务端反馈信息并打印String info = bufIn.readLine();System.out.println("info:"+info);//如果服务端的反馈信息中包含“欢迎”表面登陆成功,跳出循环if(info.contains("欢迎"))break;}//关闭流对象和客服端bufr.close();s.close();}}//创建线程封装服务端针对多个客户端的校验代码class UserThread implements Runnable{private Socket s;UserThread(Socket s){this.s = s;}public void run(){//获取客户端IP并打印String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"....connected");try{//通过for循环控制次数for(int x=0; x<3; x++){//由Socket对象得到输入流,并构造相应的BufferedReader对象BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));//读取客户端提交的数据String name = bufIn.readLine();//如果数据已经为空,则结束循环,(否则将以null为读取的到的数据进行无意义的判断)if(name==null)break;//构造BufferedReader对象并关联存储用户名的文件对象。BufferedReader bufr = new BufferedReader(new FileReader("user.txt"));PrintWriter out = new PrintWriter(s.getOutputStream(),true);String line = null;//定义一个标记记录校验结果,默认为falseboolean flag = false;while((line=bufr.readLine())!=null){//如果匹配成功则结束循环并将标记置为trueif(line.equals(name)){flag = true;break;}}//根据标记在服务端输出相应提示,并向客户端写出相应提示。if(flag){System.out.println(name+",已登录");out.println(name+",欢迎光临");//标记为true则结束三次校验循环break;}else{System.out.println(name+",尝试登录");out.println(name+",用户名不存在");}}//关闭客户端s.close();}catch (Exception e){throw new RuntimeException(ip+"校验失败");}}}//服务端class  LoginServer{public static void main(String[] args) throws Exception{//创建服务端SercerSocket对象,并监听端口ServerSocket ss = new ServerSocket(10008);//由于可能存在多个客户端,使用while循环while(true){//通过accept方法获取连接过来的客户端对象Socket s = ss.accept();//创建用户线程并开启new Thread(new UserThread(s)).start();}}}

 

------- java学习型技术博客、期待与您交流 ----------