该示例实现的功能是质数判断
程序实现的功能为客户端程序接收用户输入的数字
然后将用户输入的内容发送给服务器端
服务器端判断客户端发送的数字是否是质数
并将判断的结果反馈给客户端
客户端根据服务器端的反馈显示判断结果
质数的规则是最小的质数是只能被和自身整除的自然数当用户输入小于的数字以及输入的内容不是自然数时都属于非法输入
网络程序的功能都分为客户端程序和服务器端程序实现下面先描述一下每个程序分别实现的功能
客户端程序功能
a) 接收用户控制台输入
b) 判断输入内容是否合法
c) 按照协议格式生成发送数据
d) 发送数据
e) 接收服务器端反馈
f) 解析服务器端反馈信息并输出
服务器端程序功能
a) 接收客户端发送数据
b) 按照协议格式解析数据
c) 判断数字是否是质数
d) 根据判断结果生成协议数据
e) 将数据反馈给客户端
分解好了网络程序的功能以后就可以设计网络协议格式了如果该程序的功能比较简单所以设计出的协议格式也不复杂
客户端发送协议格式
将用户输入的数字转换为字符串再将字符串转换为byte数组即可
例如用户输入则转换为字符串使用getBytes转换为byte数组
客户端发送quit字符串代表结束连接
服务器端发送协议格式
反馈数据长度为个字节数字代表是质数代表不是质数代表协议格式错误
例如客户端发送数字则反馈发送则反馈发送则反馈
功能设计完成以后就可以分别进行客户端和服务器端程序的编写了在编写完成以后联合起来进行调试即可
下面分别以TCP方式和UDP方式实现该程序注意其实现上的差异不管使用哪种方式实现客户端都可以多次输入数据进行判断对于UDP方式来说不需要向服务器端发送quit字符串
以TCP方式实现的客户端程序代码如下
package example;
import javaio*;
import *;
/**
* 以TCP方式实现的质数判断客户端程序
*/
public class TCPPrimeClient {
static BufferedReader br;
static Socket socket;
static InputStream is;
static OutputStream os;
/**服务器IP*/
final static String HOST = ;
/**服务器端端口*/
final static int PORT = ;
public static void main(String[] args) {
init() //初始化
while(true){
Systemoutprintln(请输入数字)
String input = readInput() //读取输入
if(isQuit(input)){ //判读是否结束
byte[] b = quitgetBytes()
send(b)
break; //结束程序
}
if(checkInput(input)){ //校验合法
//发送数据
send(inputgetBytes())
//接收数据
byte[] data = receive()
//解析反馈数据
parse(data)
}else{
Systemoutprintln(输入不合法请重新输入!)
}
}
close() //关闭流和连接
}
/**
* 初始化
*/
private static void init(){
try {
br = new BufferedReader(
new InputStreamReader(Systemin))
socket = new Socket(HOSTPORT)
is = socketgetInputStream()
os = socketgetOutputStream()
} catch (Exception e) {}
}
/**
* 读取客户端输入
*/
private static String readInput(){
try {
return brreadLine()
} catch (Exception e) {
return null;
}
}
/**
* 判断是否输入quit
* @param input 输入内容
* @return true代表结束false代表不结束
*/
private static boolean isQuit(String input){
if(input == null){
return false;
}else{
if(quitequalsIgnoreCase(input)){
return true;
}else{
return false;
}
}
}
/**
* 校验输入
* @param input 用户输入内容
* @return true代表输入符合要求false代表不符合
*/
private static boolean checkInput(String input){
if(input == null){
return false;
}
try{
int n = IntegerparseInt(input)
if(n >= ){
return true;
}else{
return false;
}
}catch(Exception e){
return false; //输入不是整数
}
}
/**
* 向服务器端发送数据
* @param data 数据内容
*/
private static void send(byte[] data){
try{
oswrite(data)
}catch(Exception e){}
}
/**
* 接收服务器端反馈
* @return 反馈数据
*/
private static byte[] receive(){
byte[] b = new byte[];
try {
int n = isread(b)
byte[] data = new byte[n];
//复制有效数据
Systemarraycopy(b data n)
return data;
} catch (Exception e){}
return null;
}
/**
* 解析协议数据
* @param data 协议数据
*/
private static void parse(byte[] data){
if(data == null){
Systemoutprintln(服务器端反馈数据不正确!)
return;
}
byte value = data[]; //取第一个byte
//按照协议格式解析
switch(value){
case :
Systemoutprintln(质数)
break;
case :
Systemoutprintln(不是质数)
break;
case :
Systemoutprintln(协议格式错误)
break;
}
}
/**
* 关闭流和连接
*/
private static void close(){
try{
brclose()
isclose()
osclose()
socketclose()
}catch(Exception e){
eprintStackTrace()
}
}
}
在该代码中将程序的功能使用方法进行组织使得结构比较清晰核心的逻辑流程在main方法中实现
以TCP方式实现的服务器端的代码如下
package example;
import *;
/**
* 以TCP方式实现的质数判别服务器端
*/
public class TCPPrimeServer {
public static void main(String[] args) {
final int PORT = ;
ServerSocket ss = null;
try {
ss = new ServerSocket(PORT)
Systemoutprintln(服务器端已启动)
while(true){
Socket s = ssaccept()
new PrimeLogicThread(s)
}
} catch (Exception e) {}
finally{
try {
ssclose()
} catch (Exception e) {}
}
}
}
package example;
import javaio*;
import *;
/**
* 实现质数判别逻辑的线程
*/
public class PrimeLogicThread extends Thread {
Socket socket;
InputStream is;
OutputStream os;
public PrimeLogicThread(Socket socket){
thissocket = socket;
init()
start()
}
/**
* 初始化
*/
private void init(){
try{
is = socketgetInputStream()
os = socketgetOutputStream()
}catch(Exception e){}
}
public void run(){
while(true){
//接收客户端反馈
byte[] data = receive()
//判断是否是退出
if(isQuit(data)){
break; //结束循环
}
//逻辑处理
byte[] b = logic(data)
//反馈数据
send(b)
}
close()
}
/**
* 接收客户端数据
* @return 客户端发送的数据
*/
private byte[] receive(){
byte[] b = new byte[];
try {
int n = isread(b)
byte[] data = new byte[n];
//复制有效数据
Systemarraycopy(b data n)
return data;
} catch (Exception e){}
return null;
}
/**
* 向客户端发送数据
* @param data 数据内容
*/
private void send(byte[] data){
try{
oswrite(data)
}catch(Exception e){}
}
/**
* 判断是否是quit
* @return 是返回true否则返回false
*/
private boolean isQuit(byte[] data){
if(data == null){
return false;
}else{
String s = new String(data)
if(sequalsIgnoreCase(quit)){
return true;
}else{
return false;
}
}
}
private byte[] logic(byte[] data){
//反馈数组
byte[] b = new byte[];
//校验参数
if(data == null){
b[] = ;
return b;
}
try{
//转换为数字
String s = new String(data)
int n = IntegerparseInt(s)
//判断是否是质数
if(n >= ){
boolean flag = isPrime(n)
if(flag){
b[] = ;
}else{
b[] = ;
}
}else{
b[] = ; //格式错误
Systemoutprintln(n)
}
}catch(Exception e){
eprintStackTrace()
b[] = ;
}
return b;
}
/**
*
* @param n
* @return
*/
private boolean isPrime(int n){
boolean b = true;
for(int i = ;i <= Mathsqrt(n)i++){
if(n % i == ){
b = false;
break;
}
}
return b;
}
/**
* 关闭连接
*/
private void close(){
try {
isclose()
osclose()
socketclose()
} catch (Exception e){}
}
}
本示例使用的服务器端的结构和前面示例中的结构一致只是逻辑线程的实现相对来说要复杂一些在线程类中的logic方法中实现了服务器端逻辑根据客户端发送过来的数据判断是否是质数然后根据判断结果按照协议格式要求生成客户端反馈数据实现服务器端要求的功能