本文介绍如何用Java实现Socket编程。首先介绍Java针对Socket编程提供的类,以及它们之间的关系。然后分别针对TCP和UDP两种传输层协议实现Socket编程。
1 Java中的Socket编程接口介绍
Java为Socket编程封装了几个重要的类。
1.1 Socket类
Socket类实现了一个客户端socket,作为两台机器通信的终端,默认采用的传输层协议为TCP,是一个可靠传输的协议。Socket类除了构造函数返回一个socket外,还提供了connect, getOutputStream, getInputStream和close方法。connect方法用于请求一个socket连接,getOutputStream用于获得写socket的输出流,getInputStream用于获得读socket的输入流,close方法用于关闭一个流。
1.2 DatagramSocket类
DatagramSocket类实现了一个发送和接收数据报的socket,传输层协议使用UDP,不能保证数据报的可靠传输。DataGramSocket主要有send, receive和close三个方法。send用于发送一个数据报,Java提供了DatagramPacket对象用来表达一个数据报。receive用于接收一个数据报,调用该方法后,一直阻塞接收到直到数据报或者超时。close是关闭一个socket。
1.3 ServerSocket类
ServerSocket类实现了一个服务器socket,一个服务器socket等待客户端网络请求,然后基于这些请求执行操作,并返回给请求者一个结果。ServerSocket提供了bind、accept和close三个方法。bind方法为ServerSocket绑定一个IP地址和端口,并开始监听该端口。accept方法为ServerSocket接受请求并返回一个Socket对象,accept方法调用后,将一直阻塞直到有请求到达。close方法关闭一个ServerSocket对象。
1.4 SocketAddress
SocketAddress提供了一个socket地址,不关心传输层协议。这是一个虚类,由子类来具体实现功能、绑定传输协议。它提供了一个不可变的对象,被socket用来绑定、连接或者返回数值。
1.5 InetSocketAddress
InetSocketAddress实现了IP地址的SocketAddress,也就是有IP地址和端口号表达Socket地址。如果不制定具体的IP地址和端口号,那么IP地址默认为本机地址,端口号随机选择一个。
1.6. DatagramPacket
DatagramSocket是面向数据报socket通信的一个可选通道。数据报通道不是对网络数据报socket通信的完全抽象。socket通信的控制由DatagramSocket对象实现。DatagramPacket需要与DatagramSocket配合使用才能完成基于数据报的socket通信。
2. 基于TCP的Socket编程
上面描述了Java对Socket编程提供的接口,本节介绍如何实现一个基于TCP连接的Socket通信。
下面例子是Server端等待从Client端接收一条消息,然后再给客户端发送一个消息。
服务器端首先实例化ServerSocket对象,然后为其绑定一个本机地址,并开始监听。一直阻塞状态下等待客户端请求,当获得客户端连接请求后,返回一个socket对象。然后用这个socket接收一条消息,并发送一条消息。代码如下:
package server.socket.java; import java.io.IOException; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; public class SocketTcp { static private String TAG = "SocketTcp: "; public static void main(String[] args){ try { ServerSocket server = new ServerSocket(); SocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 10001); server.bind(address); System.out.println("==waiting for being connected..."); Socket client = server.accept(); System.out.println("==connected with " + client.getRemoteSocketAddress() ); PrintWriter socketOut = new PrintWriter(client.getOutputStream()); System.out.println("==waiting message from client..."); byte buf[] = new byte[1024]; if ( client.getInputStream().read(buf) > 0 ) { System.out.println("Receive Message: " + new String(buf)); } System.out.println("==sending message to client..."); String sendStr = "This is the message for client."; socketOut.write(sendStr); socketOut.flush(); socketOut.close(); client.close(); server.close(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } } }
客户端首先实例化一个socket对象,用这个对象连接服务器端。连接成功后,发送一条消息,然后等待接收一条消息。代码如下:
package client.socket.java; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; public class SocketTcp { static private String TAG = "SocketTcp: "; public static void main(String[] args){ try { final Socket socket = new Socket(); SocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 10001); System.out.println("==connecting to server ..."); socket.connect(address); PrintWriter socketOut = new PrintWriter(socket.getOutputStream()); BufferedReader socketIn = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); String sendStr = "This is the message for server."; System.out.println("==sending message to server ..."); socketOut.write(sendStr); socketOut.flush(); System.out.println("==waiting message from server ..."); String receiveStr = socketIn.readLine(); System.out.println("Receive Message: " + receiveStr); socketOut.close(); socketIn.close(); socket.close(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } finally { } } }
服务器端运行结果:
==waiting for being connected... ==connected with /172.26.176.69:53912 ==waiting message from client... Receive Message: This is the message for server.
客户端运行结果:
==connecting to server ... ==sending message to server ... ==waiting message from server ... Receive Message: This is the message for client.
3 基于UDP的Socket编程示例
基于UDP的Socket编程与基于TCP的socket编程稍有不同,socket server和client都用DatagramSocket实现。
下面例子是Server端等待从Client端接收一条消息,然后再给客户端发送一个消息。
服务器端首先实例化DatagramSocket对象,然后为其绑定一个本机地址,并开始监听。一直阻塞状态下等待从客户端接收数据报。然后从数据报中获取数据报的源地址,然后用这个源地址作为目的地址打包一个数据报,然后发送出去。代码如下:
package server.socket.java; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; public class SocketUdp { final private static String TAG = "SocketUdp: "; public static void main(String args[]) { DatagramSocket socket = null; DatagramPacket datapacket = null; InetSocketAddress address = null; try { address = new InetSocketAddress(InetAddress.getLocalHost(), 7778); socket = new DatagramSocket(address); // socket.bind(address); byte buf[] = new byte[1024]; datapacket = new DatagramPacket(buf, buf.length); System.out.println("==block for receive messages..."); socket.receive(datapacket); buf = datapacket.getData(); InetAddress addr = datapacket.getAddress(); int port = datapacket.getPort(); System.out.println("Message Content: " + new String(buf) ); System.out.println("Receive From " + addr + ":" + port); SocketAddress toAddress = datapacket.getSocketAddress(); String sendStr = "I'm Server, this is the message for client."; buf = sendStr.getBytes(); datapacket = new DatagramPacket(buf, buf.length); datapacket.setSocketAddress(toAddress); socket.send(datapacket); System.out.println("==message sended"); } catch (UnknownHostException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (SocketException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } } }
客户端首先实例化一个DatagramSocket对象。利用服务器地址和端口号作为目的地址打包一个数据报,并发送。然后等待从服务器回复的数据报。代码如下:
package client.socket.java; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; import java.net.UnknownHostException; public class SocketUdp { final private static String TAG = "SocketUdp: "; public static void main(String args[]) { try { DatagramSocket getSocket = new DatagramSocket(); DatagramPacket datapacket = null; InetSocketAddress toAddress = new InetSocketAddress(InetAddress.getLocalHost(), 7778); String sendStr = "I'm client, this is the message for server."; byte buf[] = sendStr.getBytes(); datapacket = new DatagramPacket(buf, buf.length); datapacket.setSocketAddress(toAddress); getSocket.send(datapacket); System.out.println("==message sended"); System.out.println("==block for receive messages..."); getSocket.receive(datapacket); buf = datapacket.getData(); System.out.println("Message Content: " + new String(buf)); } catch (SocketException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (UnknownHostException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.out.println(TAG + e.getMessage()); e.printStackTrace(); } } }
服务器端运行结果:
==block for receive messages... Message Content: I'm client, this is the message for server.
客户端运行结果:
==message sended ==block for receive messages... Message Content: I'm Server, this is the message for client.
0
0
« 上一篇:传输层中的TCP和UDP浅析
» 下一篇:长连接与短连接
posted on 2013-09-02 00:56 洪雁君 阅读(4109) 评论(0) 编辑 收藏
注册用户登录后才能发表评论,请 登录 或 注册,访问网站首页。
【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
【活动】阿里云双11活动开始预热 云服务器限时2折起
【调查】有奖调研即刻参与,你竟然是酱紫程序猿!
【推荐】Vue.js 2.x 快速入门,大量高效实战示例
最新IT新闻:
· 《周鸿祎自传》书摘:首谈私有化,我从没想过退出
· 一个老外的自述:“在中国手机就是我的生命”
· PayPal CEO:未来5年内 金融科技变化将远超过去30年
· 快递员回应"月薪过万":送1件提成1元 双11可挣万元
· 微软收购动态图片应用程序Swng 团队加入Skype部门
» 更多新闻...
最新知识库文章:
· 关于编程,你的练习是不是有效的?
· 改善程序员生活质量的 3+10 习惯
· NASA的10条代码编写原则
· 为什么你参加了那么多培训,却依然表现平平?
· 写给初学前端工程师的一封信
Powered by:
博客园
Copyright © 洪雁君
| ||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|---|---|---|---|---|---|
29 | 30 | 31 | 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
导航
统计
- 随笔 - 27
- 文章 - 1
- 评论 - 1
- 引用 - 0
公告
搜索
常用链接
我的标签
- Linux学习笔记(3)
- JavaScript(2)
- OTT(1)
- XMLHttpRequest(1)
- 微信(1)
随笔分类
随笔档案
- 2014年6月 (1)
- 2013年11月 (6)
- 2013年10月 (2)
- 2013年9月 (7)
- 2013年8月 (5)
- 2013年7月 (2)
- 2013年6月 (1)
- 2013年4月 (1)
- 2013年1月 (2)
相册
最新评论
- 1. Re:关于运营商向微信收费的所感
- 赞同楼主的观点!
- --刘江北
阅读排行榜
- 1. FFserver服务器实现WebM格式视频直播(4234)
- 2. 基于TCP和UDP的Socket实现(JAVA)(4109)
- 3. JavaScript中XMLHttpRequest实现跨域访问(3722)
- 4. Ubuntu通过apt-get安装Oracle JDK(1374)
- 5. 云计算面试题集锦(1261)
推荐排行榜
来源:oschina
链接:https://my.oschina.net/u/3644171/blog/1563945