三 客户与服务器程序设计
1 对现有服务编写客户程序
Smtp 简单邮件传输协议simple mail transfer protocol,使用TCP 协议,默认端口号为25
示例代码如下
/**
* Copyright (C) 2015
*
* FileName:StmpClient.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.mail;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.print.DocFlavor.STRING;
/**
* 简单邮件客户端
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class SmtpClient {
public static void main(String[] args) {
Socket smtpSocket = null;
DataOutputStream os = null;
BufferedReader is = null;
try {
smtpSocket = new Socket("sina.com", 25);
os = new DataOutputStream(smtpSocket.getOutputStream());
is = new BufferedReader(new InputStreamReader(smtpSocket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
System.err.println("do not know host: hostname");
} catch (IOException e) {
System.err.println("could not get I/O ");
}
if (smtpSocket != null && os != null) {
try {
os.writeBytes("HELO \n");
os.writeBytes("MAIL From: zhenhuayue@sina.com");
os.writeBytes("RCPT To:zhenhuayue@sina.com \n");
os.writeBytes("DATA \n");
os.writeBytes("From: 149780042@qq.com \n");
os.writeBytes("Subject:testing \n");
os.writeBytes("\n. \n");
os.writeBytes("QUIT");
String responseLine;
while ((responseLine = is.readLine()) != null) {
System.out.println("server:" + responseLine);
if ((responseLine.indexOf("OK")) != -1) {
break;
}
}
os.close();
is.close();
smtpSocket.close();
} catch (IOException e) {
System.out.println("IOException:" + e);
}
}
}
}
Finger 用于确定当前哪一个用户登录到指定计算机,也可用于探测更多用户
使用tcp协议,默认端口号为79
示例代码如下:/**
* Copyright (C) 2015
*
* FileName:Finger.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.net.finger;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 用于检测哪个用户登录到指定计算机
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class Finger {
/** 计算机名 **/
static String host = null;
/** 用户名 **/
static String user = null;
/**
* 取得计算机名
*
* @return
* @throws UnknownHostException
*/
public static String localHost() throws UnknownHostException {
InetAddress host = null;
host = InetAddress.getLocalHost();
return host.getHostName();
}
/**
* 解析方法
*
* @param str
* @throws UnknownHostException
*/
public static void parse(String str) throws UnknownHostException {
int position = 0;
while (position != -1) {
position = str.indexOf("@", position);
if (position != -1) {
host = str.substring(position + 1).trim();
user = str.substring(0, position).trim();
position++;
} else {
user = str;
host = localHost();
}
}
}
public static void main(String[] args) throws Exception {
Socket fingerSocket = null;
DataOutputStream os = null;
BufferedReader is = null;
if (args.length == 1) {
parse(args[0]);
} else {
host = localHost();
user = "@" + user;
}
try {
fingerSocket = new Socket(host, 79);
os = new DataOutputStream(fingerSocket.getOutputStream());
is = new BufferedReader(new InputStreamReader(fingerSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("count not get I/O for the connection to:" + host);
}
if (fingerSocket != null && os != null && is != null) {
try {
os.writeBytes(user);
os.writeBytes("\n");
String responseLine;
while ((responseLine = is.readLine()) != null) {
System.out.println(responseLine);
}
os.close();
is.close();
fingerSocket.close();
} catch (UnknownHostException e) {
System.err.println("trying to connect to unknow host:" + e);
} catch (IOException e) {
System.err.println("IOException" + e);
}
}
}
}
Ping客户程序 packet interNet groper,作用是通过向远程主机发送ICMP echo请求并等待一个响应,来检查主机是否可达
注:icmp需要通过socket_ram类型的socket来产生,java不支持
示例代码如下:
/**
* Copyright (C) 2015
*
* FileName:Ping.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.net;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 检查目标主机是否可达
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class Ping {
public final static int ECHO_PORT = 7;
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("usage: java ping hostname");
System.exit(0);
}
if (alive(args[0])) {
System.out.println(args[0] + " is alive");
} else {
System.out.println("no response from " + args[0] + ". host is down or does not exist!");
}
}
/**
* 检查目标主机是否可达
*
* @param host
* @return
*/
private static boolean alive(String host) {
Socket pingSocket = null;
try {
pingSocket = new Socket(host, ECHO_PORT);
} catch (UnknownHostException e) {
System.err.println("UnknownHostException: " + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
if (pingSocket != null) {
try {
pingSocket.close();
} catch (IOException e) {
System.err.println("IOException: " + e);
}
return true;
} else {
return false;
}
}
}
2 使用线程进行编程
创建并行运行线程,有两种方法Thread 和实现runnable接口
另外还可以使用线程池Executors或第三方框架amino,在java8中好像添加了新的实现方法
示列代码如下:
/**
* Copyright (C) 2015
*
* FileName:MyThread.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.thread;
public class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(getName() + ":" + i);
try {
//Thread.sleep(500);
TimeUnit.MICROSECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread("readFromSocket");
MyThread t2 = new MyThread("readFromKeyBoard");
t1.start();
t2.start();
}
}
/**
* Copyright (C) 2015
*
* FileName:MyThread2.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.thread;
/**
* 使用实现runnable接口的方法来开启线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class MyThread2 implements Runnable {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2();
MyThread2 t2 = new MyThread2();
new Thread(t1, "readFromSocket").start();
new Thread(t2, "readFromKeyBoard").start();
}
@Override
public void run() {
for (int i = 0; i < 3; i++)
try {
{
System.out.println(Thread.currentThread() + " : " + i);
//Thread.sleep(500);
TimeUnit.MICROSECONDS.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用线程睡眠 老版本sleep();
新TimeUnit.MICROSECONDS.sleep(100);
使用join等待另处一个线程结束,示例代码如下:
/**
* Copyright (C) 2015
*
* FileName:JoinTest.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.thread;
import java.util.concurrent.TimeUnit;
/**
* 使用join等待另处一个线程结束
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class JoinTest extends Thread {
static int result = 0;
public JoinTest(String name) {
super(name);
}
public static void main(String[] args) {
System.out.println("主线程执行...");
// 开始子线程
Thread t = new JoinTest("计算线路程");
t.start();
System.out.println("result:" + result);
try {
long start = System.nanoTime();
t.join();
long end = System.nanoTime();
System.out.println((end - start) / 1000000 + "毫秒后: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
System.out.println(this.getName() + "开始计算...");
try {
TimeUnit.MICROSECONDS.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = (int) (Math.random() * 10000);
System.out.println(this.getName() + "计算结束");
}
}
控制线程 ,以下三个方法都已过时
t1.stop(); //停止 可用定义标识或是interrupted
t1.resume(); //重新启动线程
t1.suspend(); //挂起一个线程
响应线程中断Thread.interrupted()来取消线程,示例代码如下:
/**
* Copyright (C) 2015
*
* FileName:InterruptTest.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.thread;
/**
* 使用interrupt来取消线程
*
* 主线程等待计算线程2000毫秒后,中断计算线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class InterruptTest extends Thread {
static int result = 0;
public InterruptTest(String name) {
super(name);
}
public static void main(String[] args) {
System.out.println("主线程执行...");
// 开始子线程
Thread t = new InterruptTest("计算线程");
t.start();
System.out.println("result:" + result);
try {
long start = System.nanoTime();
t.join(10);
long end = System.nanoTime();
t.interrupt();
System.out.println((end - start) / 1000000 + "毫秒后: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
System.out.println(this.getName() + "开始计算...");
// 方法一
// try {
// Thread.sleep(4000);
// } catch (InterruptedException e) {
// System.out.println(this.getName() + "被中断,结束");
// return;
// }
// result = (int) (Math.random() * 10000);
// System.out.println(this.getName() + "计算结束");
// 方法二
for (int i = 0; i < 1000000; i++) {
result++;
if (Thread.interrupted()) {
System.out.println(this.getName() + "被中断,结束");
return;
}
}
System.out.println(this.getName() + "计算结束");
}
}
改变线程优先级
同步 synchronization
使用synchronization访问标识符
/**
* Copyright (C) 2015
*
* FileName:BankAccount.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.thread;
/**
* 同步
*
* 使用同步标识符
*
* 使用同步代码段
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class BankAccount {
private int number;
private int balance;
public BankAccount(int number, int balance) {
this.number = number;
this.balance = balance;
}
public int getBalance() {
return this.balance;
}
/**
* 存款
*
* @param amount
*/
public synchronized void deposit(int amount) {
balance = balance + amount;
}
/**
* 取款
*
* @param amount
*/
public synchronized void withdraw(int amount) {
balance = balance - amount;
}
public static void main(String[] args) throws InterruptedException {
BankAccount account = new BankAccount(1, 1000);
Thread t1 = new Thread(new Despositor(account, 100), "depositor");
Thread t2 = new Thread(new Withdrawer(account, 100), "wiithdraw");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(account.getBalance());
}
/**
* 存款线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
static class Despositor implements Runnable {
BankAccount account;
int amount;
public Despositor(BankAccount account, int amount) {
this.account = account;
this.amount = amount;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
account.deposit(amount);
}
}
}
/**
* 取款线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
static class Withdrawer implements Runnable {
BankAccount account;
int amount;
public Withdrawer(BankAccount account, int amount) {
this.account = account;
this.amount = amount;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
account.withdraw(amount);
}
}
}
}
使用synchronization代码段
/**
* Copyright (C) 2015
*
* FileName:BankAccount.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-16
*/
// Package Information
package cn.yue.test.thread;
/**
* 同步
*
* 使用同步标识符
*
* 使用同步代码段
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
public class BankAccount {
private int number;
private int balance;
public BankAccount(int number, int balance) {
this.number = number;
this.balance = balance;
}
public int getBalance() {
return this.balance;
}
/**
* 存款
*
* @param amount
*/
public void deposit(int amount) {
synchronized (this) {
balance = balance + amount;
}
}
/**
* 取款
*
* @param amount
*/
public void withdraw(int amount) {
synchronized (this) {
balance = balance - amount;
}
}
public static void main(String[] args) throws InterruptedException {
BankAccount account = new BankAccount(1, 1000);
Thread t1 = new Thread(new Despositor(account, 100), "depositor");
Thread t2 = new Thread(new Withdrawer(account, 100), "wiithdraw");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(account.getBalance());
}
/**
* 存款线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
static class Despositor implements Runnable {
BankAccount account;
int amount;
public Despositor(BankAccount account, int amount) {
this.account = account;
this.amount = amount;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
account.deposit(amount);
}
}
}
/**
* 取款线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-16
*
*/
static class Withdrawer implements Runnable {
BankAccount account;
int amount;
public Withdrawer(BankAccount account, int amount) {
this.account = account;
this.amount = amount;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
account.withdraw(amount);
}
}
}
}
3 编写新的服务器和客户端程序
示例代码如下:/**
* Copyright (C) 2015
*
* FileName:ArrayIO.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-17
*/
// Package Information
package cn.yue.test.net.concurrent;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* 数组操作
*
* 用于数组的读写和两个数组相加
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-17
*
*/
public class ArrayOption {
public ArrayOption() {
}
/**
* 写数组内容
*
* @param out
* @param arr
* @throws IOException
*/
public void writeArray(DataOutputStream out, int arr[]) throws IOException {
for (int i = 0; i < arr.length; i++) {
out.write(arr[i]);
}
}
/**
* 读取数组内容
*
* @param br
*/
public int[] readArray(BufferedReader br) throws Exception {
int e[] = new int[10];
for (int h = 0; h < 10; h++) {
try {
e[h] = br.read();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return e;
}
/**
* 两个数组相加
*
* @param a
* @param b
* @return
*/
public int[] addArray(int a[], int b[]) {
int result[] = new int[10];
for (int s = 0; s < result.length; s++) {
result[s] = a[s] + b[s];
}
return result;
}
}
/**
* Copyright (C) 2015
*
* FileName:Client.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-17
*/
// Package Information
package cn.yue.test.net.concurrent;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* 支持并发访问的客户端
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-17
*
*/
public class Client {
public final static int REMOTE_PORT = 3333;
static int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
static int b[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
/**
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) {
Socket c1 = null;
Socket c2 = null;
BufferedReader is = null;
DataOutputStream os = null;
ArrayOption ao = new ArrayOption();
try {
c1 = new Socket("localhost", REMOTE_PORT);
is = new BufferedReader(new InputStreamReader(c1.getInputStream()));
os = new DataOutputStream(c1.getOutputStream());
} catch (UnknownHostException e) {
System.out.println("unknown host: " + e);
} catch (IOException e) {
System.out.println("error io: " + e);
}
try {
ao.writeArray(os, a);
ao.writeArray(os, b);
} catch (IOException e) {
System.out.println("error writing to server..." + e);
}
// 从服务器接收数据
int result[] = new int[10];
try {
result = ao.readArray(is);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("the sum of the two arrays: ");
for (int j = 0; j < result.length; j++) {
System.out.println(result[j] + " ");
}
System.out.println(" ");
try {
is.close();
os.close();
c1.close();
} catch (IOException e) {
System.out.println("error writing..." + e);
}
}
}
/**
* Copyright (C) 2015
*
* FileName:Server.java
*
* Author:<a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* CreateTime: 2015-1-17
*/
// Package Information
package cn.yue.test.net.concurrent;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import sun.print.resources.serviceui;
/**
* 支持并发访问的服务器端
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-17
*
*/
public class Server extends Thread {
public static final int MATH_PORT = 3333;
protected ServerSocket listen;
public Server() {
try {
listen = new ServerSocket(MATH_PORT);
} catch (IOException e) {
System.out.println("exception.." + e);
}
// 启动监听
this.start();
}
@Override
public void run() {
try {
while (true) {
Socket client = listen.accept();
Connects cs = new Connects(client);
}
} catch (IOException e) {
System.out.println("exception..." + e);
}
}
public static void main(String[] args) {
new Server();
}
}
/**
* 连接线程
*
* @version
*
* @Description:
*
* @author <a href="mailto:zhenhuayue@sina.com">Retacn</a>
*
* @since 2015-1-17
*
*/
class Connects extends Thread {
Socket client;
BufferedReader is;
DataOutputStream os;
ArrayOption ao = new ArrayOption();
public Connects(Socket s) {
client = s;
try {
is = new BufferedReader(new InputStreamReader(client.getInputStream()));
os = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
try {
client.close();
} catch (IOException e1) {
System.out.println("error getting socket stream ..." + e);
}
return;
}
this.start();
}
@Override
public void run() {
int a1[] = new int[10];
int a2[] = new int[10];
try {
a1 = ao.readArray(is);
a2 = ao.readArray(is);
} catch (Exception e) {
e.printStackTrace();
}
int r[] = new int[10];
r = ao.addArray(a1, a2);
try {
ao.writeArray(os, r);
} catch (IOException e) {
e.printStackTrace();
}
}
}