TCP网络程序的工作原理。TCP客户端程序与TCP服务器端程序交互的过程:
①服务器程序创建一个ServerSocket,然后调用accept方法等待客户来连接。
②客户端程序创建一个Socket并请求与服务器建立连接。
③服务器接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接。
④建立了连接的两个Socket在一个单独的线程(由服务器程序创建)上的对话。
⑤服务器开始等待新的连接请求,当新的连接请求到达时重复②到⑤的过程。
简单的TCP服务器程序:
TCP服务器程序必须先启动运行,TCP客户程序才能连接上TCP服务器。
①使用windows提供的telnet程序测试TCP服务器程序。
我的电脑IP为:192.168.1.103 端口号:8001
telnet 192.168.1.103 8001
②使用BufferedReader包装类,从网络输入流中一次读取一行文本。
InputStream ips=new InputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(ips));
③如何打开telnet程序的本地回显功能。
windows xp 系统为:
set localecho
程序代码:
package TCPSocket;
import java.net.*;
import java.io.*;
public class TcpServer {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
ServerSocket ss=new ServerSocket(8001);
Socket s=ss.accept();
//构建输入输出流对象用于向客户端输出数据和读取客户端的数
据
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
ops.write("abc--china".getBytes());
//构建字节数组对象读取数据
BufferedReader br=new BufferedReader(new
InputStreamReader(ips));
System.out.println(br.readLine());
/*该方法一读取到数据就向客户端发送数据 程序停止关闭连接
* byte [] buf=new byte[1024];
int len=ips.read(buf);
//将读取到的字节数组数据转化为字符数据
System.out.println(new String(buf,0,len));*/
//ips.close();
br.close();
ops.close();
s.close();
ss.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
该程序只能完成服务器与一个客户端的数据交换,与实际应用有差别,需要改进。
改进后的程序:
ReverseSocket类:
package TCPSocket;
import java.net.*;
public class ReverseServer {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
ServerSocket ss=new ServerSocket(8001);
boolean bRuning=true;
while(bRuning){
Socket s=ss.accept();
new Thread(new servicer(s)).start();
}
ss.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
servicer类:
package TCPSocket;
import java.net.*;
import java.io.*;
public class servicer implements Runnable {
private Socket s=null;
public servicer(Socket s){
this.s=s;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
BufferedReader br=new BufferedReader(
new InputStreamReader(ips));
//为了方便打印一行内容到客户端 定义一个PrintWriter包装ops对象
//设置为true很关键 将会刷新缓冲区保证读取的字符能输出到客户端屏幕上
PrintWriter pw=new PrintWriter(ops,true);
/*调用println方法将字符串写入到底层输出流,并在字符串后增加换行符
在windows下产生:"/r/n";在Linux下产生:"/n"
与PrintStream中println()方法的区别: 无论在哪种系统下产生的都是"/n"换行符 、
*/
while(true){
String StrLine=br.readLine();
if(StrLine.equalsIgnoreCase("quit")){
break;
}
System.out.println(StrLine+":"+StrLine.length());
//调用StringBuffer的reverse()方法反向排列其传入的字符串
String strEcho = new StringBuffer(StrLine).reverse().toString();
pw.println(StrLine+"-->"+strEcho);
}
br.close();
pw.close();
s.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
/*说明:在本程序中如果在客户端输入有backspace键那么在程序反向排列的过程中也会有backspace
* 例如:abc(backspace)d-->d(backspace)cba 在客户端看到的是abd 反向排序后返回的是cba
* */
TCP服务器程序模块的编写要点总结:
①TCP服务器程序要想接收多个客户端的连接,需要循环调用ServerSocket.accept方法
②服务器程序与每个客户端连接的会话过程不能相互影响,需要在独立的线程中运行。
③一个线程对象与一个服务器端Socket对象相关联,共同来完成与一个客户端的会话。