java实现的基于TCP网络编程步骤

来源:互联网 发布:柏拉图网络建网站 编辑:程序博客网 时间:2024/06/14 06:53

参考 java 程序设计教程(第二版)雍俊海老师编著的书12章

服务器端程序设计模型的建立通常由如下五个步骤组成:

(1)在服务器端,首先要创建ServerSocket的实例对象,注册在服务器端进行连接的端口号以及允许连接的最大客户数目。

(2)调用ServerSocket的成员方法accept来等待并监听来自客户端的连接。当有客户端与改服务器端建立连接时,类ServerSocket的成员方法accept将返回连接通道在服务器端的Socket。套接字的类型是Socket,通过该套接字可以与客户端进行数据通信。

(3)调用类Socket的成员方法getInputStream和getOutputStream获得该套接字所对应的输入流(InputStream)和输出流(OutputStream)。当使用套接字网络上传送对象时候,需要进行序列化。

(4)通过获得的输入流和输出流与客户端进行数据通信,并处理从客户端获得的数据以及需要向客户端发送的数据。

(5)在数据通信完毕之后,关闭输入流、输出流和套接字(Socket)。

在服务器端创建类ServerSocket的实例对象,并且调用类Serversocket的成员方法accept之后,服务器端开始一直等待客户端与其连接。

客户端程序设计模型的建立通常由如下四个步骤组成:

(1)在客户端,创建Socket的实例对象,与服务器端建立连接。在创建Socket的实例对象时需要制定服务器端的主机名以及进行连接的端口号,即在服务器端构造类Serversocket实例对象时所注册的端口号。主机名与端口号完全匹配才能建立起连接,并构造出类Socket的实例对象。在构造出类Socket的实例对象之后的步骤与服务器端的相应步骤基本一致。

(2)调用类Socket的成员方法getInputStream和getOutputStream获得该套接字所对应的输入流(InputStream)和输出流(OutputStream)。当使用套接字网络上传送对象时候,需要进行序列化。

(3)通过获得的输入流和输出流与客户端进行数据通信,并处理从服务器端获得的数据以及需要向服务器端发送的数据。

(4)在数据通信完毕之后,关闭输入流、输出流和套接字(Socket)。

服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。 
    客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

C/S模式套接字的连接示意图:

例子

(1)服务器端单一向客户端发消息,客户端收到消息,一次通信结束,客户端程序结束,而服务器端继续等待下一个客户端的连接。终止程序,要在控制台同时按ctrl +c.

结果如下图:


代码如下

服务器端:

package wjl;import java.io.DataOutputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class J_Server{public static void main(String[] args){int port = 8083;try{ServerSocket server = new ServerSocket(port);while(true){Socket client = server.accept();System.out.println("服务器端接收到来自客户端的连接");OutputStream o = client.getOutputStream();DataOutputStream d = new DataOutputStream(o);d.writeUTF("服务器端向客户端问好");//writeUTF()将两个字节长度信息写入输出流,紧随其后的是修改后的字符串中的每个字符的utf - 8表示。d.close();o.close();}}catch(Exception e){e.printStackTrace();}}}

客户端

package wjl;import java.io.DataInputStream;import java.io.InputStream;import java.net.Socket;public class J_Client{public static void main(String[] args){int port = 8083;try{Socket client = new Socket("localhost",port);InputStream o = client.getInputStream();DataInputStream d = new DataInputStream(o); System.out.println("客户端收到:" + d.readUTF());//readUTF()读到的是以UTF格式编码的输入流中的字符,返回字符串。d.close();o.close();}catch (Exception e){// TODO: handle exceptione.printStackTrace();}}}

(2)服务器端和客户端都可以收发消息,不过一次通信后,服务器端和客户端都运行结束了。

结果如下图:


服务器端

package wjl;import java.io.BufferedOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;class  WebServer{public static void main(String[] args) { int port = 9999;/*开辟一个端口就是开启一个服务了---端口的分配必须是唯一的,因为端口是为了唯一标识每台计算机唯一服务的          * 端口号是从0~65535之间的,前1024个端口已被Tcp/Ip作为保留端口,因此自己分配的端口只能是1024以后的*/  try{ServerSocket server = new ServerSocket(port);//创建服务器端套接字Socket client = server.accept();//监听器。服务器端建立自己的套接字OutputStream o = client.getOutputStream();//服务器端打开自己的输出流BufferedOutputStream b = new BufferedOutputStream(o);//使用带缓存的输出流        InputStream i = client.getInputStream();//服务器端打开自己输入流o.write("hello,I am server".getBytes());//服务器hello,I am server写入输出流--》客户端b.write("hello,I am server".getBytes());b.flush();byte[] buf = new byte[100];//存储套接字通道中读到的服务器端输出流的字符流int len = i.read(buf);//read(byte[] b)从当前服务器端的输入流中(即客户端的输出流)读取出来存储到字符数组buf中,该方法返回的是读出的字符数组长度。System.out.println(new String(buf,0,len));//客户端--》服务器 。new String(buf,0,len)是将字符数组buf从下标零到len的每个字符构成一个字符串//System.out是java.io.OutputStream类型的变量o.close();//服务器端关闭输出流b.close();i.close();//客户端关闭输入流client.close();//客户端关闭套接字server.close();//服务端关闭套接字}catch (Exception e){// TODO Auto-generated catch blocke.printStackTrace();}}}

客户端

package wjl;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;public class WebClient {public static void main(String[] args) {int port=9999;try{Socket client = new Socket(InetAddress.getByName("localhost"),port);//创建客户器端套接字//InetAddress---表示互联网协议(IP)地址  ---InetAddress.getByName("www.163.com")--在给定主机名的情况下确定主机的IP地址--如果参数为null,获得的是本机的IP地址OutputStream o = client.getOutputStream();//打开客户端的输出流InputStream i = client.getInputStream();//打开客户端的输入流byte[] buf = new byte[100];int len = i.read(buf);System.out.println(new String(buf,0,len));//服务器--》客户端o.write("hello,I am client".getBytes());//客户端hello,I am client写到输出流--》服务器.write(byte[] b)将字节数组b的各个字节写入当前文件中。o.close();//关闭客户端的输出流i.close();//关闭客户端的输入流client.close();//关闭套接字}catch(Exception e){e.printStackTrace();}}}


0 0