设计任务:客户端向服务器发送一字符串,并能读取服务器返回的字符串。
知识点:TCP套接字技术,C/S软件架构程序设计
重点理解:Java客户套接字类Socket和服务器套接字类ServerSocket,以及字符串读/写类BuffferedReader/PrintWriter。
功能详细描述:
客户端程序1:TCPClient.java具有网络接收和发送能力的程序。
客户端程序2:TCPClientJFrame.java为界面模块。
服务器程序:TCPServer.java具有网络接收和发送功能。
1、程序设计第一步:
新建一个程序包,建议命名为socketTCP;
制作并运行TCPServer程序,通过命令行窗口(netstat -an)察看是否已开启8008监听端口。
TCPServer的运行问题,TCPServer只能运行一次,且自身不能终止运行,要终止它运行,需要点击“运行”、“停止构建”。
套接字类有两个基本的方法可以获得两个通信管道的入口:
Socket.getInputStream()方法可获得输入字节流的入口地址;
Socket.getOutputStream()方法可获得输出字节流的出口地址;
2、程序设计第二步:
制作并理解TCPCilent.java程序;
(1)定义对象构造方法:
socket=new Socket(host,port);//向服务进程发起TCP三次握手连接.
Socket连接成功后,通过调用GET方法,可获得字节输出流和字节输入流,输出流用于发送信息,输入流用于接收信息。
(2)定义网络信息发送方法供外部调用:
public void send(String msg) {
pw.println(msg); //写入网卡输出流,由系统调用底层函数,经网卡发送
}
(3)定义网络信息接收方法供外部调用:
public String receive(){
String msg;
try {
msg = br.readLine();//接收一行信息,阻塞语句。
} catch (IOException ex) { msg=null; }
return msg;
}
(4)定义网络连接关闭方法供外部调用
public void close() {
try {
if(socket!=null)
socket.close();//实现四次握手断开,如图2.3所示.
} catch (IOException ex) { }
}
3、程序设计第三步:
创建窗体:
在“连接”按钮中设置如下动作:
String ip=jTextField2.getText();
String port=jTextField3.getText();
try {
ec=new TCPClient(ip,port);
jTextArea1.append("服务器连接成功.\r\n");
} catch (IOException ex) {
jTextArea1.append("服务器连接失败.\r\n");
}
在“发送”按钮中添加网络发送和接收方法:
String msg1=jTextField1.getText();
ec.send(msg1);//发送一串字符。
String msg2=ec.receive(); //接收一行字符串。
jTextArea1.append(msg2);
附件1:
TCPClient.java源文件如下:
import java.net.*;
import java.io.*;
public class TCPClient {
//套接字程序设计.
private Socket socket=null;
//用于字节和字符之间转换用的变量.
private PrintWriter pw;中
private BufferedReader br;
public TCPClient(String ip,String port) throws IOException{
socket=new Socket(ip,Integer.parseInt(port));
//主动向服务器发起连接,实现TCP中三次握手的过程。
//若不成功(网络问题,地址错误,服务器资源紧张等),抛出错误,其错误信息交由调用者处理。
//若成功,做下面两件事情。
OutputStream socketOut = socket.getOutputStream();
pw=new PrintWriter(new OutputStreamWriter(socketOut,"GB2312"),true);
//得到网络输出字节流地址,并装饰成网络输出字符流
InputStream socketIn = socket.getInputStream();
br=new BufferedReader(new InputStreamReader(socketIn,"GB2312"));
//得到网络输入字节流地址,并装饰成网络输入字符流
}
public void send(String msg){
pw.println(msg);
//输出字符流,由Socket调用系统底层函数,经网卡发送字节流。
}
public String receive(){
String msg;
try {
msg = br.readLine();
//从网络输入字符流中读信息,每次只能接收一行信息.
//若不够一行(无行结束符),该语句阻塞(阻塞语句),直到条件满足,程序才往下运行
} catch (IOException ex) { msg=null; }
return msg;
}
public void close() {
try {
if(socket!=null)
socket.close();//实现四次握手断开.
} catch (IOException ex) { }
}
//模块内测试与运行,需先运行TCPServer。
public static void main(String args[]) throws IOException{
TCPClient tc=new TCPClient("127.0.0.1","8008");
ec.send("123456789");//发送一行字符串
System.out.println(ec.receive());//接收一行字符串并在屏幕上显示
ec.close();
}
}
附件2:
TCPServer.java源文件如下:
import java.io.*;
import java.net.*;
public class TCPServer {
private int port=8008;
private ServerSocket serverSocket;//服务器套接字。
public TCPServer() throws IOException {
serverSocket = new ServerSocket(8008);//开启8008号监听端口。
System.out.println("服务器启动");
}
private PrintWriter putWriter(Socket socket)throws IOException{
OutputStream socketOut = socket.getOutputStream();//获得输出流缓冲区的地址。
return new PrintWriter(new OutputStreamWriter(socketOut,"GB2312"),true);
}
private BufferedReader getReader(Socket socket)throws IOException{
InputStream socketIn = socket.getInputStream();//获得输入流缓冲区的地址
return new BufferedReader(new InputStreamReader(socketIn,"GB2312"));
}
public void service() {//单客户版本,即每次只能同时和一个客户建立通信连接。
while (true) {
Socket socket=null;
try {
socket = serverSocket.accept();
//阻塞语句,监听并等待客户发起连接,有连接请求就生成一个套接字。
System.out.println("New income: "+socket.getInetAddress());
//本地服务器观测台显示请求的用户信息。
BufferedReader br =getReader(socket);//定义字符串输入流。
PrintWriter pw = putWriter(socket);//定义字符串输出流。
String msg;
while ((msg = br.readLine())!= null) //阻塞语句,从输入流中读入一行字符串。
{
pw.println("来自服务器:"+msg);//向输出流中输出一行字符串。
//pw.println("来自服务器2:"+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 {
new TCPServer().service();
}
}