Java Socket编程与客户/服务器应用开发(三)
来源:互联网 发布:河北工龄工资算法 编辑:程序博客网 时间:2024/06/03 15:04
流式Socket API:
数据包Socket API支持离散数据单元(即数据包)交换,流式Socket API则提供了基于UNIX操作系统的流式IO的数据传输模式。
根据定义,流式Socket API仅支持面向连接通信。
流式Socket为两个特定进程提供稳定的数据交换模型。数据流从一方连续写入,从另一方读出。流的特性允许以不同速度向流中写入或读取数据,但是一个流式Socket 不能用于同时与两个及其以上的进程通信。
在Java中,有两个类提供了流式Socket API:ServerSocket和Socket。
1)ServerSocket用于接受连接,称之为连接Socket。
2)Socket用于数据交换,称之为数据Socket。
采用该API,服务器进程建立一个连接Socket,随后侦听来自其他进程的连接请求。每次只接受一个连接请求。当连接被接受后,将为该连接创建一个数据Socket。服务器进程可通过数据Socket从数据流读取数据或向其中写入数据。一旦两进程之间的通信会话结束,数据Socket被关闭,服务器可通过连接Socket自由接收下一个连接请求。
客户进程创建一个Socket,随后通过服务器的连接Socket向服务器发送连接请求。一旦请求被接受,客户Socket与服务器数据Socket连接,以便客户可继续从数据流读取数据或向数据流写入数据。当两进程之间的通信会话结束后,数据Socket关闭。
ServerSocket 的 accept()方法是阻塞操作,如果没有正在等待的请求,服务器进程被挂起,直到连接请求到达。
Socket 的输入流中读取数据时,即InputStream的read()方法是阻塞操作,如果请求的所有数据没有全部到达该输入流中,客户进程将被阻塞,直到有足够数量的数据被写入数据流。
public class SocketServerConnectionAcceptor { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { //服务器监听端口 int portNo=9527; ServerSocket connectionSocket = new ServerSocket(portNo); System.out.println("now ready accept a connection~"); //阻塞监听连接 Socket dataSocket=connectionSocket.accept(); //可以从socket里获得发送方的地址和端口,以及接收方的地址和端口 System.out.println(dataSocket.getInetAddress()+" "+dataSocket.getPort()+" " +dataSocket.getRemoteSocketAddress()+" "+dataSocket.getLocalPort()+" " +dataSocket.getLocalAddress()); System.out.println("connection accepted:"); OutputStream outputStream=dataSocket.getOutputStream(); PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream)); for(int i=0;i<5;i++) { String msg=scanner.nextLine(); printWriter.println(msg); printWriter.flush(); } System.out.println("message sent!!"); //先关掉数据Socket dataSocket.close(); System.out.println("data socket closed!"); //再关掉连接Socket connectionSocket.close(); System.out.println("connection socket closed!"); } catch (Exception e) { e.printStackTrace(); } }}
public class SocketConnectionRequestor { public static void main(String []args) { try { //服务器地址和端口号 InetAddress acceptorHost = InetAddress.getByName("127.0.0.1"); int acceptorPort=9527; SocketAddress socketAddress = new InetSocketAddress(acceptorHost, acceptorPort); //数据Socket Socket mySocket = new Socket(); //最大等待连接时长 int timeoutPeriod=5000; mySocket.connect(socketAddress,timeoutPeriod); System.out.println("Connection request granted!!"); //可以从socket里获得发送方的地址和端口,以及接收方的地址和端口 System.out.println(mySocket.getInetAddress()+" "+mySocket.getPort()+" " +mySocket.getRemoteSocketAddress()+" "+mySocket.getLocalPort()+" " +mySocket.getLocalAddress()); InputStream inputStream=mySocket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); System.out.println("waiting to read!!"); for(int i=0;i<5;i++) { String msg=bufferedReader.readLine(); System.out.println("Message received:"); System.out.println("\t"+msg); } mySocket.close(); System.out.println("data socket closed!!"); } catch (Exception e) { e.printStackTrace(); } }}
以上是服务器写数据,客户端读数据;其实完全可以双方都写、读。
当使用PrintWriter向 Socket流写入数据时,必须使用flush()方法调用来真正地填充与刷新该流,从而确保所有数据都可以在像Socket突然关闭等意外情形发生之前,尽可能快地从数据缓冲区中真正地写入数据流。
为允许将程序中的应用逻辑和服务逻辑分离,采用了隐藏数据Socket细节的子类。
public class MyStreamSocket{ private Socket socket; private BufferedReader input; private PrintWriter output; MyStreamSocket(String acceptorHost, int acceptorPort ) throws SocketException, IOException{ socket = new Socket(acceptorHost, acceptorPort ); setStreams(); } MyStreamSocket(Socket socket) throws IOException { this.socket = socket; setStreams(); } private void setStreams( ) throws IOException{ // 从输入流中获取inputStream InputStream inStream = socket.getInputStream(); input = new BufferedReader(new InputStreamReader(inStream)); OutputStream outStream = socket.getOutputStream(); // 创建一个PrintWriter来操作字符流 output = new PrintWriter(new OutputStreamWriter(outStream)); } public void sendMessage(String message) throws IOException { output.println(message); //flush操作为了避免意外关闭socket而导致数据丢失 output.flush(); } // end sendMessage public String receiveMessage( ) throws IOException { // 从输入流读取一行 return input.readLine( ); } //end receiveMessage public void SocketClose() throws IOException{ socket.close(); }} //end class
使用以上封装好的Socket操作:
public class ServerSocketConnectionAcceptor { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { int portNo=9527; ServerSocket serverSocket = new ServerSocket(portNo); System.out.println("now ready accept a connection~"); MyStreamSocket dataSocket = new MyStreamSocket(serverSocket.accept()); System.out.println("connection accepted:"); for(int i=0;i<5;i++) { dataSocket.sendMessage(scanner.nextLine()); } dataSocket.SocketClose(); System.out.println("data socket closed!"); serverSocket.close(); System.out.println("connection socket closed!"); } catch (Exception e) { e.printStackTrace(); } }}
public class SocketConnectionRequestor { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { int serverPortNo=9527; String serverHost = "127.0.0.1"; MyStreamSocket dataSocket = new MyStreamSocket(serverHost,serverPortNo); System.out.println("connection request granted:"); for(int i=0;i<5;i++) { System.out.println(dataSocket.receiveMessage()); } dataSocket.SocketClose(); System.out.println("data socket closed!"); } catch (Exception e) { e.printStackTrace(); } }}
以上是服务器为单线程,若加入多线程:
public class MyStreamSocket implements Runnable{ private Socket socket; private BufferedReader input; private PrintWriter output; MyStreamSocket(String acceptorHost, int acceptorPort ) throws SocketException, IOException{ socket = new Socket(acceptorHost, acceptorPort ); setStreams(); } MyStreamSocket(Socket socket) throws IOException { this.socket = socket; setStreams(); } ...... @Override public void run() { Scanner scanner = new Scanner(System.in); try { System.out.println("connection accepted:"); for(int i=0;i<5;i++) { sendMessage(scanner.nextLine()); } SocketClose(); System.out.println("data socket closed!"); } catch (Exception e) { e.printStackTrace(); } }} //end class
public class ServerSocketThreadConnectionAcceptor { public static void main(String[] args) { try { int portNo=9527; ServerSocket serverSocket = new ServerSocket(portNo); System.out.println("now ready accept a connection~"); while (true) { Socket socket=serverSocket.accept(); new Thread(new MyStreamSocket(socket)).start(); }// serverSocket.close();// System.out.println("connection socket closed!"); } catch (Exception e) { e.printStackTrace(); } }}
- Java Socket编程与客户/服务器应用开发(三)
- Java Socket编程与客户/服务器应用开发(一)
- Java Socket编程与客户/服务器应用开发(二)
- socket编程(TCP多进程客户与服务器)
- Java Socket编程(三)服务器Sockets
- Java Socket编程(三) 服务器Sockets
- linux网络编程之socket(三):最简单的回射客户/服务器程序
- java socket编程(服务器与客户端)
- 服务器开发【三】----网络编程的基础SOCKET(3)
- java 服务器与客户断对话,socket,多线程
- 1.7 客户/服务器应用编程
- socket编程(TCP单进程客户服务器通信)
- Java Socket编程(三) 并发服务器
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- Charactor controller
- 实现带复选框的下拉列表
- 0416 css超链接
- win10 默认程序 edge
- 0416 盒子模型
- Java Socket编程与客户/服务器应用开发(三)
- LeetCode 521. Longest Uncommon Subsequence I
- 初识java
- MFC Windows程序设计--工具栏,状态栏,组合栏
- IDEA的草稿功能,瞬间变为强大的文本编辑器
- Wing IDE安装与破解方法
- HDU
- Could not find helloworld.apk
- 第64天(就业班) springmvc