<分布式程序设计> 读书笔记三

三 客户与服务器程序设计

对现有服务编写客户程序

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  ");

os.writeBytes("MAIL From: zhenhuayue@sina.com");

os.writeBytes("RCPT To:zhenhuayue@sina.com  ");

os.writeBytes("DATA  ");

os.writeBytes("From: 149780042@qq.com  ");

os.writeBytes("Subject:testing  ");

os.writeBytes(" .  ");

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(" ");

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;

}

}

}

使用线程进行编程

创建并行运行线程,有两种方法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);

}

}

}

}

编写新的服务器和客户端程序

示例代码如下:/**

 * 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();

}

}

}

原文地址:https://www.cnblogs.com/retacn-yue/p/6194237.html