实验2《Windows Socket编程》
一、实验目的
通过实验,使学生熟悉并掌握计算机Windows 编程的基本知识,进一步加深学生对课堂所学基本内容的理解,掌握基本的Windows编程技巧,通过实验使得学生能够进行一些简单的网络程序设计。
二、实验内容
- 了解基本的Socket知识
- 基于java完成Socket编程,设计并实现一个简单的聊天系统,包括客户端及服务器端。
2.1 完成服务端使用telnet与服务器通信
2.2 完成客户端与服务端通信
2.3 完成基于多线程的实现服务端可以与多个客户端通信 - 可选,重构现有代码完成带界面的软件。实现各客户端之间聊天,以及多人聊天室。
三、实验方法
实验方法为利用Intellij IDEA开发工具,JAVA编程语言实现,参考过往实验资料与网络资料之后自己实现完成。
四、实验步骤
-
开启本机的telnet服务,在终端输入telnet可进行连接,输入?可查看帮助信息。
-
打开Intellij IDEA开发工具进行项目程序编写;
2.1 实现了一个简单的服务端: start函数负责建立服务端,等待连接,stop函数负责关闭连接以及相关的io流。Serversocket对象创建以后accept函数等待客户端连接。若没有客户端连接上,则会一直轮询,直到有客户端连接上,继续执行下面逻辑。当建立连接以后,双方建立通信管道,io流读取与写入数据。完成socket通信。//sampleServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;public class sampleServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;//建立服务端,等待连接 public void start(int port) throws Exception{ serverSocket = new ServerSocket(port); clientSocket = serverSocket.accept(); out = new PrintWriter(clientSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null){ if(".".equals(inputLine)){ out.println("good bye"); stop(); break; }else{ out.println("server got msg: "+inputLine); } } } //关闭连接以及相关的io流 public void stop() throws Exception{ in.close(); out.close(); clientSocket.close(); serverSocket.close(); } public static void main(String[] args){ try { sampleServer server = new sampleServer(); server.start(23); }catch (Exception ex){ ex.printStackTrace(); } }
}
此时,可以使用telnet连接,输入信息,即可发送给服务端。服务端接收到处理后返回。
2.2 完成客户端与服务端通信
在完成了可以使用telnet连接,并与之通信的服务器以后,我们编写自己的客户端代码与服务器进行通信。代码很简单。
StartConnection函数指定ip与端口,若与服务器成功建立连接,则获取建立的通道的io流,out与in输入输出流,来实现后续与服务端的消息接收与发送。
sendMessage函数基于io流发送消息。
StopConnection关闭与服务端的连接。
主函数获得用户在命令行的输入,发送给服务端。
//sampleClient.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class sampleClient {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
//指定ip和端口
public void startConnection(String ip, int port)throws Exception{
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(),true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
//基于IO流发消息
public String sendMessage(String msg)throws Exception{
out.println(msg);
String resp = in.readLine();
return resp;
}
//关闭与服务端的连接
public void stopConnection(){
try {
in.close();
out.close();
clientSocket.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
public static void main(String[] args){
try{
//bulid the connection
sampleClient client = new sampleClient();
client.startConnection("127.0.0.1",23);
//recevice the input string from termnal and send it to server
Scanner sc = new Scanner((System.in));
while (true){
String response = client.sendMessage(sc.nextLine());
System.out.println(response);
if(response.equals("good bye")){
client.stopConnection();
break;
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
2.3 完成基于多线程的实现服务端可以与多个客户端通信
完成以上实验,即可使用socket实现客户端与服务端之间的交互,进行简单的消息发送与接收。接下来我们可以实现多线程技术。
将上面服务器代码的获取io流,收发消息代码移植到clientHandler类中,该类继承自thread类。
修改start函数,依然是在本地的一个端口进行监听,但是我们这里使用一个循环来将每一个连接上来的client交给clientHandler来进行处理,这样主进程就不会阻塞,可以继续接收新客户端的连接,从而实现一个服务端连接多个客户端并与之通信的功能。
同时需要注意,我们使用一个clientList来维护所有的客户端。代码如下所示:
//clientList.java
import java.util.ArrayList;
public class clientList {
public static ArrayList clientList;
static {
clientList = new ArrayList<multiServer.clientHandler>();
}
}
//multiServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class multiServer {
private ServerSocket serverSocket;
public void start(int port)throws Exception{
serverSocket = new ServerSocket(port);
while (true){
clientHandler client = new clientHandler(serverSocket.accept());
clientList.clientList.add(client);
client.start();
}
}
public void stop() throws Exception{
serverSocket.close();
}
public static class clientHandler extends Thread{
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public clientHandler(Socket socket){
this.clientSocket = socket;
}
public void run(){
try{
out = new PrintWriter(clientSocket.getOutputStream(),true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null){
if(".".equals(inputLine)){
out.println("good bye");
break;
}
out.println("msg from client" + clientList.clientList.indexOf(this) + "--msg:" + inputLine);
}
in.close();
out.close();
clientSocket.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
}
}
//main.java
public class main {
public static void main(String[] args){
try{
new multiServer().start(23);
}catch (Exception ex){
ex.printStackTrace();
}
}
}
五、实验结果
实验运行步骤及结果如下所示:
- 在Intellij IDEA中运行main函数;
- 运行命令行,输入telnet,连接telnet服务,再输入o,输入连接主机 localhost;
- 接下来便可以运行第一个客户端,客户端即可输入信息,服务端可以反馈;
- 重复第二步第三步即可开启多个客户端;
六、实验小结
本次实验是要是了解socket编程知识,客户端与服务端的交互,多阅读相关资料熟悉实验中需使用的方法就会轻松很多。