Java 实现简单Socket 通信的示例
Javasocket封装了传输层的实现细节,开发人员可以基于socket实现应用层。本文介绍了Javasocket简单用法。
1.传输层协议
传输层包含了两种协议,分别是TCP(TransmissionControlProtocol,传输控制协议)和UDP(UserDatagramProtocol,用户数据报协议)。
TCP是一种面向连接,可靠的流协议。通信双方在“发送-接收”数据之前需要先建立TCP连接,然后通过互相发送二进制数据流来进行通信。所谓连接,指的是各种设备、线路,或网络中进行通信的应用程序为了相互传递消息而建立的专有、虚拟的通信线路。连接一旦建立,进行通信的应用程序只使用该虚拟的通信线路发送和接收数据。TCP还需要处理端到端之间的流量控制。
UDP是一种无连接的,不可靠的数据报协议。发送方不需要与接收方建立连接,通信双方通过发送一个个独立的数据报来进行通讯。
TCP通过序列号、确认应答、数据校验等机制确保了传输的可靠性,适用于需要可靠数据传输的场景,应用层协议HTTP,FTP基于TCP。UDP没有复杂的控制机制,不纠错,不重发,不保证数据的准确性,不确保数据到达目的地;不过UDP传送等量数据花费更小的流量,适用于对时延要求高但对准确性要求不高的场景,如视频、音频通讯。
Java中有3种套接字类,java.net.Socket和java.net.ServerSocket基于TCP,java.net.DatagramSocket基于UDP。
2.TCP示例
TCP是面向连接的,所以在进行通讯之前发送端(客户端)需要先连接到接收端(服务端)。客户端通过newSocket("localhost",9090)来创建一个连接到服务端的套接字,这个套接字连接到主机localhost的9090端口。
ServerSocket实现服务端套接字,通过newServerSocket(9090)来创建一个监听端口为9090实例;ServerSocket.accept()方法会阻塞等待客户端的连接,一旦有连接过来,会返回一个服务端的Socket实例。连接建立完成,客户端Socket实例和服务端Socket实例就可以面向输入输出流发送数据了。
2.1示例效果
客户端程序接收控制台输入的内容,客户端控制台每输入一行,就往服务端发送,服务端接收到消息之后,将消息打印到控制台。
客户端输入"Bye"时,客户端断开与服务端的连接,客户端程序退出,服务端程序继续等待连接。
客户端控制台输入输出:
$javaServer.java BindPort9090 Newclientconnected. ReceivedMessage-->AreyouOK!
服务端控制台输出:
$javaClient.java AreyouOK! SendMsg-->AreyouOK! Bye $
2.2服务端程序代码
importjava.net.*; importjava.io.*; classServer{ publicstaticvoidmain(String[]args){ //ServerSocket实现了AutoCloseable接口,所以支持try-with-resource语句 //创建一个ServerSocket,监听9090端口 try(ServerSocketserv=newServerSocket(9090)){ System.out.printf("BindPort%d\n",serv.getLocalPort()); Socketsocket=null; while(true){ //接收连接,如果没有连接,accept()方法会阻塞 socket=serv.accept(); //获取输入流,并使用BufferedInputStream和InputStreamReader装饰,方便以字符流的形式处理,方便一行行读取内容 try(BufferedReaderin=newBufferedReader(newInputStreamReader(socket.getInputStream()))){ Stringmsg=null; char[]cbuf=newchar[1024]; intlen=0; while((len=in.read(cbuf,0,1024))!=-1){//循环读取输入流中的内容 msg=newString(cbuf,0,len); if("Bye".equals(msg)){//如果检测到"Bye",则跳出循环,不再读取输入流中内容。 break; } System.out.printf("ReceivedMessage-->%s\n",msg); } }catch(IOExceptione){ e.printStackTrace(); } } }catch(IOExceptione){ e.printStackTrace(); } } } 2.3客户端程序代码 importjava.net.*; importjava.io.*; importjava.util.*; classClient{ publicstaticvoidmain(String[]args){ try(Socketsocket=newSocket("localhost",9090)){ BufferedWriterout=newBufferedWriter(newOutputStreamWriter(socket.getOutputStream())); Scannerscanner=newScanner(System.in); scanner.useDelimiter("\r\n"); Stringmsg=null; while(!(msg=scanner.next()).equals("Bye")){ System.out.printf("SendMsg-->%s\n",msg); out.write(msg); out.flush();//立即发送,否则需要积累到一定大小才一次性发送 } }catch(IOExceptione){ e.printStackTrace(); } } }
3.UDP示例
UDP不需要连接,客户端与服务端通过发送数据报来完成通信。Java中使用java.net.DatagramSocket来表示UDP客户端或服务端的套接字,使用java.net.DatagramPacket来表示UDP的数据报。客户端和服务端可以直接向对方发送数据报,不需要进行连接。
下面代码基于UDP实现了与上面程序同样的功能。不过消息可能会出错,某些消息可能也不能到达服务端。
3.1服务端程序代码
importjava.net.*; importjava.io.*; classServer{ publicstaticvoidmain(String[]args){ //创建一个DatagramPacket实例,用来接收客户端发送过来的UDP数据报,这个实例可以重复利用。 byte[]buf=newbyte[8192];//缓存区 intlen=buf.length;//要利用的缓存区的大小 DatagramPacketpac=newDatagramPacket(buf,len); //创建服务端的套接字,需要指定绑定的端口号 try(DatagramSocketserv=newDatagramSocket(9191)){ while(true){ serv.receive(pac);//接收数据报。如果没有数据报发送过来,会阻塞 System.out.println("Message-->"+newString(pac.getData(),0,pac.getLength())); } }catch(IOExceptione){ e.printStackTrace(); } } }
3.2客户端程序代码
importjava.io.*; importjava.net.*; importjava.util.*; classClient{ publicstaticvoidmain(String[]args){ //创建一个客户端的UDP套接字,不需要指定任何信息 try(DatagramSocketclient=newDatagramSocket()){ //创建一个数据报实例,数据和长度在发送之前都会重新设置,所以这里直接置为0即可。 //由于是发送端,所以需要设置服务端的地址和端口 DatagramPacketpac=newDatagramPacket(newbyte[0],0,InetAddress.getByName("localhost"),9191); //扫描控制台输入 Scannerscanner=newScanner(System.in); scanner.useDelimiter("\r\n"); Stringmsg=null; while(!(msg=scanner.next()).equals("Bye")){ //设置要发送的数据 pac.setData(msg.getBytes()); //发送数据报 client.send(pac); System.out.println("SentMessage-->"+msg); } }catch(IOExceptione){ e.printStackTrace(); } } }
需要注意的是,UDP是面向无连接的,但DatagramSocket的API中提供了带有connect字样的方法,这里的connect并非TCP中连接的意思。而是指定了当前的UDP套接字只能够向指定的主机和端口发送数据报。
以上就是Java实现简单Socket通信的示例的详细内容,更多关于Java实现Socket通信的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。