一.用java编写的入门客户/服务器通信程序

本篇文章观点和例子来自 《Java网络编程精解》, 作者为孙卫琴, 出版社为电子工业出版社。

Java 网络程序都采用客户/服务器通信模式, 致力于实现应用层。 传输层向应用层提供了套接字 Socket 接口, Socket 封装了下层的数据传输细节, 应用层的程序通过 Socket 来建立与远程主机的连接, 以及进行数据传输。

站在应用层的角度,两个进程之间的一次通信过程从建立连接开始,接着交换数据,到断开连接结束。 套接字可看做是通信线路两端的接收器,进程通过套接字来收发数据。

如 进程A1-------Socket <------tcp连接----->Socket-------进程B1

在Java中, 有3种套接字类: java.net.Socket、java.net.ServerSocket 和 DatagramSocket。 其中 Socket 和 ServerSocket 类建立在 TCP协议基础上; DatagramSocket 类建立在UDP协议基础上。

  • 创建 EchoClient

package com.sockettest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class EchoClient {
private String host = "localhost";//EchoServer进程所在的主机的名字,这里为"localhost"表示EchoClient和EchoServe
//进程运行在同一个主机上.
private int port = 8000; //EchoServer进程监听的端口
private Socket socket;

public EchoClient() throws IOException{
if(socket == null){
socket = new Socket(host,port);//如果Socket对象成功创建,就表示建立了EchoClient和EchoServer之间的连接.
System.out.println("连接服务器!");
}
}

private PrintWriter getWriter(Socket socket) throws IOException{
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);
}

private BufferedReader getReader(Socket socket) throws IOException{
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}

/**
* EchoClient 类中最主要的方法. 该方法不断读取用户从控制台输入的字符串, 然后把它发送给 EchoServer, 再把EchoServer
* 返回的字符串打印到控制台. 如果用户输入的字符串为 "bye", 就会结束与 EchoServer的通信, 调用socket.close()方法断开
* 连接.
*/
public void talk() {
try{
//EchoClient和EchoServer建立连接后, EchoClient从Socket对象中得到输出流和输入流, 就能与EchoServer交换数据.
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);

BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));

String msg = null;
while((msg = localReader.readLine())!= null){
pw.println(msg); //输出信息到服务器
System.out.println(br.readLine()); //打印从服务器接受的信息

if(msg.equals("bye")) //如果客户发送的信息为"bye",就结束通信
break;
}


}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(socket != null) socket.close();//断开连接
}catch(IOException e){e.printStackTrace();}
}
}


public static void main(String args[])throws IOException{
new EchoClient().talk();
}
}

  • 创建 EchoServer

package com.sockettest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {

private int port = 8000;
private ServerSocket serverSocket;

public EchoServer() throws IOException{
if(serverSocket == null){
//服务器程序通过一直监听端口, 来接受客户程序的连接请求. 在服务器程序中, 需要先创建一个ServerSocket对象,
//在构造方法中指定监听的端口.
//ServerSocket的构造方法负责在操作系统中把当前 进程注册为服务器进程.
serverSocket = new ServerSocket(port); //监听8000端口
System.out.println("服务器启动!");
}
}

public String echo(String msg){
return "echo:" + msg;
}

//Socket类提供getOutputStream()方法,返回输出流OutputSteam对象,程序只需向输出流写数据, 就能向对方发送数据,
//Socket的输出流可以用过滤留来装饰, 这个方法中先获取输出流, 然后用PrintWriter装饰它, PrintWriter的
//println()方法能够写一行数据.
private PrintWriter getWriter(Socket socket) throws IOException{
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);//参数true表示每写一行, PrintWriter缓存就自动溢出, 把数据写到目的地
}

//Socket类提供getInputStream()方法, 返回输入流InputStream对象, 程序只需从输入流读数据,就能接收来自对方的数据,
//Socket的输入流也可以用过滤流来装饰, 这个方法中先获取输入流, 然后用BufferedReader装饰它, BufferedReader的
//readLine()方法能够读入一行数据.
private BufferedReader getReader(Socket socket) throws IOException{
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}

/**
* EchoServer 类最主要的方法, 它不断等待客户的连接请求, 当serverSocket.accept()方法返回一个Socket对象时,
* 就意味着与一个客户建立了连接,接下来从Socket对象中得到输出流和输入流, 并且分别用PrintWriter 和BufferedReader
* 来装饰它们. 然后不断调用 BufferedReader 的readLine()方法读取客户发来的字符串XXX, 再调用PrintWriter 的
* println()方法向客户返回字符串 echo:XXX. 当客户发来的字符串为 "bye" 时, 就会结束与客户的通信,
* 调用socket.close() 方法断开连接.
* PS.这个方法无法同时与多个客户通信. EchoServer接收到一个客户连接, 就与客户进行通信, 通信完毕后断开连接,然后再
* 接收下一个客户连接. 假如同时有多个客户请求连接, 这些客户就必须排队等候EchoServer的响应.
*/
public void service(){
while(true){
Socket socket = null;
try{
//服务器程序调用ServerSocket对象的accept()方法, 该方法一直监听端口, 等待客户的连接请求, 如果接受到一个
//连接请求, accept()方法就会返回一个Socket对象, 这个Socket对象与客户端的Scoket对象形成了一条通信线路.
socket = serverSocket.accept(); //等待客户连接

//Socket对象包含了客户的地址和端口
System.out.println("New connection accepted "
+ socket.getInetAddress() + " : " + socket.getPort());

BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);

String msg = null;
while((msg = br.readLine()) != null){
System.out.println(msg);//打印接受的信息
pw.println(echo(msg));//输出信息到客户端
if(msg.equals("bye"))//如果客户端发送的信息为"bye", 就结束通信
break;
}

}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(socket != null) socket.close();//断开连接
}catch(IOException e){
e.printStackTrace();}
}
}
}



public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
new EchoServer().service();
}

}

先运行 EchoServer, 再运行 EchoClient, 在EchoClient的控制台中输入字符串, 当输入的字符串为bye时, 就会结束与EchoServer的通信.

转载自:http://blog.csdn.net/lin49940/article/details/4382143

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值