开发客户端代码
我们可以按以下的步骤开发基于多线程的服务器端的代码。
第一步,在3.2里创建的“TCPSocket”项目里,新建一个名为ThreadServer.java的代码文件,创建文件的方式大家可以参照3.2部分的描述。首先编写package和import部分的代码,用来打包和引入包文件,如下所示:
package tcp;
import java.io.*;
import java.net.*;
第二步,由于我们在服务器端引入线程机制,所以我们要编写线程代码的主体执行类ServerThreadCode,这个类的代码如下所示:
class ServerThreadCode extends Thread
{
//客户端的socket
private Socket clientSocket;
//IO句柄
private BufferedReader sin;
private PrintWriter sout;
//默认的构造函数
public ServerThreadCode()
{}
public ServerThreadCode(Socket s) throws IOException
{
clientSocket = s;
//初始化sin和sout的句柄
sin = new BufferedReader(new InputStreamReader(clientSocket
.getInputStream()));
sout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
clientSocket.getOutputStream())), true);
//开启线程
start();
//线程执行的主体函数
public void run()
{
try
{
//用循环来监听通讯内容
for(;;)
{
String str = sin.readLine();
//如果接收到的是byebye,退出本次通讯
if (str.equals("byebye"))
{
break;
}
System.out.println("In Server reveived the info: " + str);
sout.println(str);
}
System.out.println("closing the server socket!");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
System.out.println("close the Server socket and the io.");
try
{
clientSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
这个类的业务逻辑说明如下:
1. 这个类通过继承Thread类来实现线程的功能,也就是说,在其中的run方法里,定义了该线程启动后要执行的业务动作。
2. 这个类提供了两种类型的重载函数。在参数类型为Socket的构造函数里, 通过参数,初始化了本类里的Socket对象,同时实例化了两类IO对象。在此基础上,通过start方法,启动定义在run方法内的本线程的业务逻辑。
3. 在定义线程主体动作的run方法里,通过一个for(;;)类型的循环,根据IO句柄,读取从Socket信道上传输过来的客户端发送的通讯信息。如果得到的信息为“byebye”,则表明本次通讯结束,退出for循环。
4. catch从句将处理在try语句里遇到的IO错误等异常,而在finally从句里,将在通讯结束后关闭客户端的Socket句柄。
上述的线程主体代码将会在ThreadServer类里被调用。
第三步,编写服务器端的主体类ThreadServer,代码如下所示:
public class ThreadServer
{
//端口号
static final int portNo = 3333;
public static void main(String[] args) throws IOException
{
//服务器端的socket
ServerSocket s = new ServerSocket(portNo);
System.out.println("The Server is start: " + s);
try
{
for(;;)
{
//阻塞,直到有客户端连接
Socket socket = s.accept();
//通过构造函数,启动线程
new ServerThreadCode(socket);
}
}
finally
{
s.close();
}
}