客户-服务器一对一通信
一直对Socket不是很了解,但这个确实很有用,为弄懂只能看看资料,写写事例了,下面是我仿的一些希望对大家有点帮助:
1.客户-服务器一对一通信流程图
2.服务端与客户端代码
服务端: SingleServer.java
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
/**
*
* @author nassir wen
*
*/
public class SingleServer {
public SingleServer(){
init();
waitForClient();
}
private void init(){
try {
server = new ServerSocket(port);
//超时值为 0 被解释为无穷大超时值
server.setSoTimeout(0);
//套接字在其上侦听的端口
log.info("[Server listen on port:" + server.getLocalPort()+"]");
} catch (IOException e) {
log.error(e);
}
}
private void waitForClient(){
try {
log.info("Wait for client...");
//侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞
socket = server.accept();
//获取套接字绑定的本地地址
log.info("Client's ip:" + socket.getLocalAddress());
log.info("Client's port:" + socket.getPort());
} catch (IOException e) {
log.error(e);
}
}
private void communicate(){
try {
while(!isStop){
//返回此套接字的输入流
inStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//返回此套接字的输出流
outStream = socket.getOutputStream();
while((readline = inStream.readLine()) != null){
//当客户端输入stop的时候,服务器停止运行
if("stop".equals(readline)){
log.info("Client want to leave...");
isStop = true;
break;
}else{
System.out.println("Client said:"+readline);
int data = -1;
System.out.print("Server said:");
/**
* 此流已打开并准备提供输入数据。
* 通常,此流对应于键盘输入或者由主机环境
* 或用户指定的另一个输入源
*/
while((data=System.in.read()) != -1){
outStream.write((byte)data);
/*
* 如果读到的data是换行符 这里 '/n' 是字符,
* 转换成整型数值后与data进行比较
*/
if(data == '/n'){
/**
* 刷新此输出流并强制写出所有缓冲的输出字节。
* flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,
* 则调用此方法指示应将这些字节立即写入它们预期的目标。
* 如果此流的预期目标是由基础操作系统提供的一个抽象(如一个文件),
* 则刷新此流只能保证将以前写入到流的字节传递给操作系统进行写入,
* 但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。
*/
outStream.flush();
break;
}
}
}
}
}
} catch (IOException e) {
log.error(e);
}finally{
try {
inStream.close();
outStream.close();
socket.close();
log.info("Server closed!");
} catch (IOException e) {
log.error(e);
}
System.exit(0);
}
}
static public void main(String[] args) {
//加裁日志文件
PropertyConfigurator.configure("conf/log4j/log4j.properties");
SingleServer singleServer = new SingleServer();
singleServer.communicate();
}
private static Log log = LogFactory.getLog(SingleServer.class);
private final static int port = 9000;
private ServerSocket server = null;
private Socket socket = null;
//数据输入流允许应用程序以与机器无关方式
//从基础输入流中读取基本 Java 数据类型。
//应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
private DataInputStream inStream=null;
//OutputStream:此抽象类是表示输出字节流的所有类的超类。
//输出流接受输出字节并将这些字节发送到某个接收器
private OutputStream outStream=null;
private String readline = null;
private boolean isStop = false;
}
客户端:SingleClient.java
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
/**
*
* @author nassir wen
*
*/
public class SingleClient {
public SingleClient() {
init();
}
private void init() {
try {
// 创建通讯并且和服务端主机连接
client = new Socket("127.0.0.1", 9000);
} catch (UnknownHostException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}
}
private void communicate() {
try {
inStream = new DataInputStream(client.getInputStream());
outStream = client.getOutputStream();
int data = -1;
while (!isStop) {
System.out.print("Call server:");
// 从标准输入输出接收字符并且写入系统
while ((data = System.in.read()) != -1) {
outStream.write((byte) data);
if (data == '/n') {
outStream.flush();
// 将程序阻塞,直到回答信息被接收到后将他们显示在标准输出上
responseline = inStream.readLine();
if(responseline == null || "".equals(responseline)){
isStop = true;
break;
}
System.out.println("Server said:" + responseline);
System.out.print("Client said:");
}
}
}
} catch (IOException e) {
log.error(e);
} finally {
try {
inStream.close();
outStream.close();
client.close();
log.info("Client closed!");
} catch (IOException e) {
log.error(e);
}
System.exit(0);
}
}
public static void main(String[] args) {
PropertyConfigurator.configure("conf/log4j/log4j.properties");
SingleClient singleClient = new SingleClient();
singleClient.communicate();
}
private static Log log = LogFactory.getLog(SingleClient.class);
private Socket client = null;
private DataInputStream inStream = null;
private OutputStream outStream = null;
private boolean isStop = false;
private String responseline = null;
}
注意:
1.日志所须jar要导入
2.服务端先启动并确保端口没有被占用(本例port:9000)