Java网络socket编程详解.pdf
《Java网络socket编程详解.pdf》由会员分享,可在线阅读,更多相关《Java网络socket编程详解.pdf(30页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、或许有点长 但是一步步教你 我想你也愿意看 7.2 面向套接字编程 我们已经通过了解 Socket 的接口, 知其所以然, 下面我们就将通过具体的案例, 来熟悉 Socket 的具体工作方式 7.2.1 使用套接字实现基于 TCP 协议的服务器和客户机程序 依据 TCP 协议,在 C/S 架构的通讯过程中,客户端和服务器的 Socket 动作如下: 客户端: 1.用服务器的 IP 地址和端口号实例化 Socket 对象。 2.调用 connect 方法,连接到服务器上。 3.将发送到服务器的 IO 流填充到 IO 对象里,比如 BufferedReader/PrintWriter。 4.利用
2、Socket 提供的 getInputStream 和 getOutputStream 方法,通过 IO 流对象,向服务器发 送数据流。 5. 通讯完成后,关闭打开的 IO 对象和 Socket。 服务器: 1. 在服务器,用一个端口来实例化一个 ServerSocket 对象。此时,服务器就可以这个端口 时刻监听从客户端发来的连接请求。 2.调用 ServerSocket 的 accept 方法,开始监听连接从端口上发来的连接请求。 3.利用 accept 方法返回的客户端的 Socket 对象,进行读写 IO 的操作 通讯完成后,关闭打开的流和 Socket 对象。 7.2.1.1 开发客
3、户端代码 根据上面描述的通讯流程,我们可以按如下的步骤设计服务器端的代码。 第一步,依次点击 Eclipse 环境里的“文件”|“新建”|“项目”选项,进入“新建项目” 的向导对话框,在其中选中“Java 项目” ,点击“下一步”按钮,在随后弹出的对话框里, 在其中的“项目名”一栏里,输入项目名“TCPSocket” ,其它的选项目 选择系统默认值,再按“完成”按钮,结束创建 Java 项目的动作。 第二步,完成创建项目后,选中集成开发环境左侧的项目名“TCPSocket” ,点击右键, 在随后弹出的菜单里依次选择“新建”!“类”的选项,创建服务器类的代码。 在随后弹出的“新建 Java 类”
4、的对话框里,输入包名“tcp” ,输入文件名“ServerCode” , 请注意大小写,在“修饰符”里选中“公用” ,在“想要创建哪些方法存根”下,选中“public static void main(String args )”单选框,同时把其它两项目取消掉,再按“完成”按钮,可 以生成代码。 第三步,在生成的代码里,编写引入 Java 包的代码,只有当我们引入这些包后,我们 才能调用这些包里提供的 IO 和 Socket 类的方法。 package tcp; import java.io.BufferedReader; import java.io.BufferedWriter; impo
5、rt java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import .ServerSocket; import .Socket; 第四步,编写服务器端的主体代码,如下所示。 public class ServerCode / 设置端口号 public static int portNo = 3333; public static void main(String args) throws IOExceptio
6、n ServerSocket s = new ServerSocket(portNo); System.out.println(The Server is start: + s); / 阻塞,直到有客户端连接 Socket socket = s.accept(); try System.out.println(Accept the Client: + socket); /设置 IO 句柄 BufferedReader in = new BufferedReader(new InputStreamReader(socket .getInputStream(); PrintWriter out =
7、 new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), true); while (true) String str = in.readLine(); if (str.equals(byebye) break; System.out.println(In Server reveived the info: + str); out.println(str); finally System.out.println(close the Server socket and the io.
8、); socket.close(); s.close(); 这段代码的主要业务逻辑是: 1.在上述代码里的 main 函数前,我们设置了通讯所用到的端口号,为 3333。 2.在 main 函数里,根据给定 3333 端口号,初始化一个 ServerSocket 对象 s,该对 象用来承担服务器端监听连接和提供通讯服务的功能。 3.调用 ServerSocket 对象的 accept 方法,监听从客户端的连接请求。当完成调用 accept 方法后,整段服务器端代码将回阻塞在这里,直到客户端发来 connect 请求。 4.当客户端发来 connect 请求,或是通过构造函数直接把客户端的 So
9、cket 对象连 接到服务器端后, 阻塞于此的代码将会继续运行。 此时服务器端将会根据 accept 方法的执行 结果,用一个 Socket 对象来描述客户端的连接句柄。 5.创建两个名为 in 和 out 的对象,用来传输和接收通讯时的数据流。 6.创建一个 while(true)的死循环,在这个循环里,通过 in.readLine()方法,读取从 客户端发送来的 IO 流(字符串) ,并打印出来。如果读到的字符串是“byebye” ,那么退出 while 循环。 7.在 trycatchfinally 语句段里,不论在 try 语句段里是否发生异常,并且不论 这些异常的种类,finally
10、 从句都将会被执行到。在 finally 从句里,将关闭描述客户端的连接 句柄 socket 对象和 ServerSocket 类型的 s 对象。 7.2.1.2 开发客户端代码 我们可以按以下的步骤,开发客户端的代码。 第一,在 TCPSocket 项目下的 tcp 包下,创建一个名为 ClientCode.java 的文件。在其中编写 引入 Java 包的代码,如下所示: package tcp; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import
11、java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import .InetAddress; import .Socket; 第二,编写客户端的主体代码,如下所示: public class ClientCode static String clientName = Mike; /端口号 public static int portNo = 3333; public static void main(String args) throws IOException /
12、设置连接地址类,连接本地 InetAddress addr = InetAddress.getByName(localhost); /要对应服务器端的 3333 端口号 Socket socket = new Socket(addr, portNo); try System.out.println(socket = + socket); / 设置 IO 句柄 BufferedReader in = new BufferedReader(new InputStreamReader(socket .getInputStream(); PrintWriteout=newPrintWriter(Buf
13、feredWriter(new OutputStreamWriter(socket.getOutputStream(), true); out.println(Hello Server,I am + clientName); String str = in.readLine(); System.out.println(str); out.println(byebye); finally System.out.println(close the Client socket and the io.); socket.close(); 上述客户端代码的主要业务逻辑是: 1.同样定义了通讯端口号,这里
14、给出的端口号必须要和服务器端的一致。 2.在 main 函数里,根据地址信息“localhost” ,创建一个 InetAddress 类型的对象 addr。这里,因为我们把客户端和服务器端的代码都放在本机运行,所以同样可以用 “127.0.0.1”字符串,来创建 InetAddress 对象。 3.根据 addr 和端口号信息,创建一个 Socket 类型对象,该对象用来同服务器端的 ServerSocket 类型对象交互,共同完成 C/S 通讯流程。 4.同样地创建 in 和 out 两类 IO 句柄,用来向服务器端发送和接收数据流。 5.通过 out 对象,向服务器端发送Hello Se
15、rver,I am 的字符串。发送后,同样 可以用 in 句柄,接收从服务器端的消息。 6.利用 out 对象,发送”byebye”字符串,用以告之服务器端,本次通讯结束。 7.在 finally 从句里,关闭 Socket 对象,断开同服务器端的连接。 7.2.1.3 运行效果演示 在上述两部分里, 我们分别讲述了 C/S 通讯过程中服务器端和客户端代码的业务逻辑, 下面 我们将在集成开发环境里,演示这里通讯流程。 第一步,选中 ServerCode.java 代码,在 eclipse 的“运行”菜单里,选中“运行方式”|“1 Java 应用程序”的菜单,开启服务器端的程序。 开启服务端程序
16、后,会在 eclipse 环境下方的控制台里显示如下的内容: The Server is start: ServerSocketaddr=0.0.0.0/0.0.0.0,port=0,localport=3333 在这里,由于 ServerSocket 对象并没监听到客户端的请求,所以 addr 和后面的 port 值都是 初始值。 第二步,按同样的方法,打开 ClientCode.java 程序,启动客户端。启动以后,将在客户端的 控制台里看到如下的信息: socket = Socketaddr=localhost/127.0.0.1,port=3333,localport=1326 Hel
17、lo Server,I am Mike close the Client socket and the io. 从中可以看到,在第一行里,显示客户端 Socket 对象连接的 IP 地址和端口号,在第二行里, 可以到到客户端向服务器端发送的字符串,而在第三行里,可以看到通讯结束后,客户端关 闭连接 Socket 和 IO 对象的提示语句。 第三步,在 eclipse 下方的控制台里,切换到 ServerCode 服务端的控制台提示信息里,我们 可以看到服务器端在接收到客户端连接请求后的响应信息。 响应的信息如下所示: The Server is start: ServerSocketaddr=
18、0.0.0.0/0.0.0.0,port=0,localport=3333 Accept the Client: Socketaddr=/127.0.0.1,port=1327,localport=3333 In Server reveived the info: Hello Server,I am Mike close the Server socket and the io. 其中,第一行是启动服务器程序后显示的信息。在第二行里,显示从客户端发送的连接请求 的各项参数。在第三行里,显示了从客户端发送过来的字符串。在第四行里,显示了关闭服 务器端 ServerSocket 和 IO 对象的提
19、示信息。从中我们可以看出在服务器端里 accept 阻塞和 继续运行的这个过程。 通过上述的操作,我们可以详细地观察到 C/S 通讯的全部流程,请大家务必要注意:一定要 先开启服务器端的程序再开启客户端, 如果这个步骤做反的话, 客户端程序会应找不到服务 器端而报异常。 7.2.2 使用套接字连接多个客户机 在 7.1 的代码里,客户端和服务器之间只有一个通讯线程,所以它们之间只有一条 Socket 信道。 如果我们在通过程序里引入多线程的机制, 可让一个服务器端同时监听并接收多个客户端的 请求,并同步地为它们提供通讯服务。 基于多线程的通讯方式, 将大大地提高服务器端的利用效率, 并能使服务
20、器端能具备完善的 服务功能。 7.2.2.1 开发客户端代码 我们可以按以下的步骤开发基于多线程的服务器端的代码。 第一步,在 3.2 里创建的“TCPSocket”项目里,新建一个名为 ThreadServer.java 的代码文 件, 创建文件的方式大家可以参照 3.2 部分的描述。 首先编写 package 和 import 部分的代码, 用来打包和引入包文件,如下所示: package tcp; import java.io.*; import .*; 第二步,由于我们在服务器端引入线程机制,所以我们要编写线程代码的主体执行类 ServerThreadCode,这个类的代码如下所示:
21、class ServerThreadCode extends Thread /客户端的 socket private Socket clientSocket; /IO 句柄 private BufferedReader sin; private PrintWriter sout; /默认的构造函数 public ServerThreadCode() public ServerThreadCode(Socket s) throws IOException clientSocket = s; /初始化 sin 和 sout 的句柄 sin = new BufferedReader(new Inpu
22、tStreamReader(clientSocket .getInputStream(); sout = new PrintWriter(new BufferedWriter(new OutputStreamWriter( clientSocket.getOutputStream(), true); /开启线程 start(); /线程执行的主体函数 public void run() try /用循环来监听通讯内容 for(;) String str = sin.readLine(); /如果接收到的是 byebye,退出本次通讯 if (str.equals(byebye) break;
23、System.out.println(In Server reveived the info: + str); sout.println(str); System.out.println(closing the server socket!); catch (IOException e) e.printStackTrace(); finally System.out.println(close the Server socket and the io.); try clientSocket.close(); catch (IOException e) e.printStackTrace();
24、这个类的业务逻辑说明如下: 1.这个类通过继承 Thread 类来实现线程的功能,也就是说,在其中的 run 方法里, 定义了该线程启动后要执行的业务动作。 2.这个类提供了两种类型的重载函数。 在参数类型为 Socket 的构造函数里, 通过 参数,初始化了本类里的 Socket 对象,同时实例化了两类 IO 对象。在此基础上,通过 start 方法,启动定义在 run 方法内的本线程的业务逻辑。 3.在定义线程主体动作的 run 方法里,通过一个 for(;)类型的循环,根据 IO 句柄, 读取从 Socket 信道上传输过来的客户端发送的通讯信息。如果得到的信息为“byebye” ,则
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 网络 socket 编程 详解
限制150内