标签:socket serversocket datagramsocket tcp udp
作品展时,我们的作品 “超级飞聊” 的主打功能就是聊天,包括局域网聊天、外网聊天等,虽然那时是用VB实现的(winsock控件),不过每种编程中的思想还是大同小异的,所以学习Java中的Socket编程时,倍感亲切啊。
Socket又称“套接字”,用来向网络中的主机发出请求或者应答网络中发出的请求。
文章开头先来简单了解一下TCP与UDP这两个协议:
TCP
TCP(Transmission Control Protocol传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,位于传输层。这三个特点中,面向连接就如同打电话,双方的电话必须保持连接状态才能通话;可靠就如同QQ上的视频,一方发送视频请求,另一方必须同意后才能建立视频连接,也可以说安全性好;基于字节流,继续看下文就行。
TCP最重要的思想就是大名鼎鼎的“三次握手”:
客户端向服务端发送请求报文,服务端收到后向客户端回复,客户端确认收到服务端的回复。三次握手完成后,客户端就与服务端建立了可靠的链接。
UDP
UDP(User Datagram Protocol用户数据报协议),提供简单但不可靠的信息传送服务。很像生活中的写信或发邮件,不需要征得对方的同意,不需要与对方建立连接,就可以将数据发送出去,但是不能保证发送出去的数据能够确保无误地到达目的地。
记得在VB中使用winsock,先往窗体上拖两个winsock控件(相当于实例化),然后给它们设置IP、端口、传输协议,就可以通信了。只不过在Java中,基于TCP协议的通信需要用ServerSocket和Socket来完成,基于UDP协议的通信需要用 DatagramSocket来完成。
下面从TCP和UDP两个方面来大概描述一下Java中如何进行网络通信。
服务端代码:
import java.io.*; import java.net.*; public class Server { public static void main(String[] args) { InputStream is=null; OutputStream os=null; try{ ServerSocket ss=new ServerSocket(5566); //创建服务器套接字并绑定到5566端口 Socket s=ss.accept(); is=s.getInputStream(); os=s.getOutputStream(); DataInputStream dis=new DataInputStream(is); DataOutputStream dos=new DataOutputStream(os); String message=null; if((message=dis.readUTF())!=null){ //接收并输出此连接的客户端发来的信息 System.out.println("Client:"+message); } dos.writeUTF("Hello, Client!"); //向此连接的客户端发送信息 dis.close(); dos.close(); s.close(); }catch(ConnectException ex){ ex.printStackTrace(); }catch(IOException ex){ ex.printStackTrace(); } } }
客户端代码:
import java.io.*; import java.net.*; public class Client { public static void main(String[] args) { InputStream is=null; OutputStream os=null; try{ Socket s=new Socket("127.0.0.1",5566); //创建一个套接字并将其连接到127.0.0.1地址(本机)的5566端口 is=s.getInputStream(); os=s.getOutputStream(); DataInputStream dis=new DataInputStream(is); DataOutputStream dos=new DataOutputStream(os); dos.writeUTF("Hello, Server!"); //向服务端发送信息 String message=null; if((message=dis.readUTF())!=null){ System.out.println("Server:"+message); //接收并输出服务端发来的信息 } dis.close(); dos.close(); s.close(); }catch(ConnectException ex){ ex.printStackTrace(); }catch(IOException ex){ ex.printStackTrace(); } } }执行结果:
客户端:
服务端:
整个连接和交互的过程如下图:
执行时,先启动服务端,服务端创建服务器套接字ServerSocket并绑定到指定的端口,当执行到Socket s=ss.accept()时,会产生“阻塞”(即让程序暂时停留在此处),但客户端启动,创建套接字Socket并向指定地址的指定端口发送请求时,ServerSocket接受服务端的请求并返回客户端的socket实例,与之建立连接。socket原意为插座,还真的挺形象的,整个过程就如同把客户端的插头插到服务端的插座上,就建立起了通道。通信完毕后,双方都关闭连接。
例子中,Socket的getInputStream()方法可以获得网络连接输入,返回此套接字的字节输入流对象;getOutputStream()方法返回此套接字的字节输出流对象,用于向连接对象写入数据。这里体现了上文中TCP的第三个特点“基于字节流”。
服务端代码:
import java.net.*; class UDPServer{ public static void main(String[] args)throws Exception{ //接收信息 DatagramSocket server = new DatagramSocket(5050); byte[] recvBuf = new byte[1000]; DatagramPacket recvPacket = new DatagramPacket(recvBuf , recvBuf.length); server.receive(recvPacket); String recvStr = new String(recvPacket.getData() , 0 , recvPacket.getLength()); System.out.println("What server has received is:" + recvStr); //发送信息 int port = recvPacket.getPort(); InetAddress addr = recvPacket.getAddress(); String sendStr = "Hello ! I'm Server"; byte[] sendBuf = new String("Hello Client! I'm Server!").getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendBuf , sendBuf.length , addr , port ); server.send(sendPacket); server.close(); } }
客户端代码:
import java.net.*; class UDPClient{ public static void main(String[] args)throws Exception{ //发送信息 DatagramSocket client = new DatagramSocket(); byte[] sendBuf=new String("Hello Server! I'm Client").getBytes(); InetAddress addr = InetAddress.getByName("127.0.0.1"); int port = 5050; DatagramPacket sendPacket = new DatagramPacket(sendBuf ,sendBuf.length , InetAddress.getByName("127.0.0.1") , port); client.send(sendPacket); //接收信息 byte[] recvBuf = new byte[100]; DatagramPacket recvPacket = new DatagramPacket(recvBuf , recvBuf.length); client.receive(recvPacket); String recvStr = new String(recvPacket.getData() , 0 ,recvPacket.getLength()); System.out.println("What client has received is:" + recvStr); client.close(); } }
整个流程如下图:
服务端启动后,准备一个包含字节数组buf的数据报包DatagramPacket用于接收客户端发来的数据报,客户端启动后,将目的地址、端口、发送内容等信息封装在DatagramPacket中,通过DatagramSocket的send()方法发往目的地(服务端),服务端将接收到的数据报放在DatagramPackage中。服务端向客户端发送数据报的过程亦然。
标签:socket serversocket datagramsocket tcp udp
原文地址:http://blog.csdn.net/huyuyang6688/article/details/44645323