java

位置:IT落伍者 >> java >> 浏览文章

Java网络编程基础(四) ServerSocket类使用


发布日期:2020年10月29日
 
Java网络编程基础(四) ServerSocket类使用

由于SSClient使用了流套接字所以服务程序也要使用流套接字

这就要创建一个ServerSocket对象ServerSocket有几个构造函数最简单的是ServerSocket(int port)当使用ServerSocket(int port)创建一个ServerSocket对象port参数传递端口号这个端口就是服务器监听连接请求的端口如果在这时出现错误将抛出IOException异常对象否则将创建ServerSocket对象并开始准备接收连接请求

接下来服务程序进入无限循环之中无限循环从调用ServerSocket的accept()方法开始在调用开始后accept()方法将导致调用线程阻塞直到连接建立在建立连接后accept()返回一个最近创建的Socket对象该Socket对象绑定了客户程序的IP地址或端口号

由于存在单个服务程序与多个客户程序通讯的可能所以服务程序响应客户程序不应该花很多时间否则客户程序在得到服务前有可能花很多时间来等待通讯的建立然而服务程序和客户程序的会话有可能是很长的(这与电话类似)因此为加快对客户程序连接请求的响应典型的方法是服务器主机运行一个后台线程这个后台线程处理服务程序和客户程序的通讯

为了示范我们在上面谈到的慨念并完成SSClient程序下面我们创建一个SSServer程序程序将创建一个ServerSocket对象来监听端口的连接请求如果成功服务程序将等待连接输入开始一个线程处理连接并响应来自客户程序的命令下面就是这段程序的代码

Listing : SSServerjava

// SSServerjavaimport javaio*;import *;import javautil*;class SSServer{public static void main (String [] args) throws IOException{Systemoutprintln (Server starting\n); // Create a server socket that listens for incoming connection// requests on port ServerSocket server = new ServerSocket ();while (true){// Listen for incoming connection requests from client// programs establish a connection and return a Socket// object that redivsents this connectionSocket s = serveraccept ();Systemoutprintln (Accepting Connection\n);// Start a thread to handle the connectionnew ServerThread (s)start ();}}}class ServerThread extends Thread{private Socket s;ServerThread (Socket s){thiss = s;}public void run (){BufferedReader br = null;PrintWriter pw = null;try{// Create an input stream reader that chains to the sockets// byteoriented input stream The input stream reader// converts bytes read from the socket to characters The// conversion is based on the platforms default character// setInputStreamReader isr;isr = new InputStreamReader (sgetInputStream ());// Create a buffered reader that chains to the input stream// reader The buffered reader supplies a convenient method// for reading entire lines of textbr = new BufferedReader (isr);// Create a print writer that chains to the sockets byte// oriented output stream The print writer creates an// intermediate output stream writer that converts// characters sent to the socket to bytes The conversion// is based on the platforms default character setpw = new PrintWriter (sgetOutputStream () true);// Create a calendar that makes it possible to obtain date// and time informationCalendar c = CalendargetInstance ();// Because the client program may send multiple commands a// loop is required Keep looping until the client either// explicitly requests termination by sending a command// beginning with letters BYE or implicitly requests// termination by closing its output streamdo{// Obtain the client programs next commandString cmd = brreadLine ();// Exit if client program has closed its output streamif (cmd == null)break;// Convert command to uppercase for ease of comparisoncmd = cmdtoUpperCase ();// If client program sends BYE command terminateif (cmdstartsWith (BYE))break;// If client program sends DATE or TIME command return// current date/time to the client programif (cmdstartsWith (DATE) || cmdstartsWith (TIME))pwprintln (cgetTime ()toString ());// If client program sends DOM (Day Of Month) command// return current day of month to the client programif (cmdstartsWith (DOM))pwprintln ( + cget (CalendarDAY_OF_MONTH));// If client program sends DOW (Day Of Week) command// return current weekday (as a string) to the client// programif (cmdstartsWith (DOW))switch (cget (CalendarDAY_OF_WEEK)){case CalendarSUNDAY : pwprintln (SUNDAY);break;case CalendarMONDAY : pwprintln (MONDAY);break;case CalendarTUESDAY : pwprintln (TUESDAY);break;case CalendarWEDNESDAY: pwprintln (WEDNESDAY);break;case CalendarTHURSDAY : pwprintln (THURSDAY);break;case CalendarFRIDAY : pwprintln (FRIDAY);break;case CalendarSATURDAY : pwprintln (SATURDAY);}// If client program sends DOY (Day of Year) command// return current day of year to the client programif (cmdstartsWith (DOY))pwprintln ( + cget (CalendarDAY_OF_YEAR));// If client program sends PAUSE command sleep for three// secondsif (cmdstartsWith (PAUSE))try{Threadsleep ();}catch (InterruptedException e){}}while (true);{catch (IOException e){Systemoutprintln (etoString ());}finally{Systemoutprintln (Closing Connection\n);try{if (br != null)brclose ();if (pw != null)pwclose ();if (s != null)sclose ();}catch (IOException e){}}}}

运行这段程序将得到下面的输出

Server starting

Accepting Connection

Closing Connection

SSServer的源代码声明了一对类SSServer 和ServerThreadSSServer的main()方法创建了一个ServerSocket对象来监听端口上的连接请求如果成功 SSServer进入一个无限循环中交替调用ServerSocket的 accept() 方法来等待连接请求同时启动后台线程处理连接(accept()返回的请求)线程由ServerThread继承的start()方法开始并执行ServerThread的run()方法中的代码

一旦run()方法运行线程将创建BufferedReader PrintWriter和 Calendar对象并进入一个循环这个循环由读(通过BufferedReader的 readLine())来自客户程序的一行文本开始文本(命令)存储在cmd引用的string对象中如果客户程序过早的关闭输出流会发生什么呢?答案是cmd将得不到赋值

注意必须考虑到这种情况在服务程序正在读输入流时客户程序关闭了输出流如果没有对这种情况进行处理那么程序将产生异常

一旦编译了SSServer的源代码通过输入Java SSServer来运行程序在开始运行SSServer后就可以运行一个或多个SSClient程序

               

上一篇:Java数据库程序中的存储过程设计

下一篇:用Java写一个在线金山词霸程序