1.设计一个基于GUI的客户-服务器的通信应用程序,如图1,图2所示。
图1 Socket通信服务器端界面
图2 Socket通信客户端界面
2.图1为Socket通信服务器端界面,点击该界面中的【Start】按钮,启动服务器监听服务(在图1界面中间的多行文本区域显示“Server starting…”字样)。图2为Socket通信客户端界面,点击该界面中的【Connect】按钮与服务器建立链接,并在图2所示界面中间的多行文本区域显示“Connect to server…”字样,当服务器端监听到客户端的连接后,在图1界面中间的多行文本区域追加一行“Client connected…”字样,并与客户端建立Socket连接。
3.当图1所示的服务器端和图2所示的客户机端建立Socket连接后,编程实现服务端、客户端之间的“单向通信”:在客户端的输入界面发送消息,在服务端接收该消息,并将接收到对方的数据追加显示在多行文本框中。
上述实验内容的基础上,尝试实现“双向通信”功能,即服务端、客户端之间可以相互发送、接收消息。
首先应该
掌握Java的网络通信编程,ServerSocket,Socket类的使用(赶紧学习一波https://www.jianshu.com/p/cde27461c226)。
掌握Java中多线程的编程,Thread类,Runnable接口的使用(可看我写的Thread的介绍)。
主要思路
重点和难点在于服务端开启的监听和接收线程.
1.服务端的接口函数
1.1若点击start
开启监听线程(这里把一些花里胡哨的输出给删除了,先看懂原理然后自己想怎么加都行)
监听到的话便开启线程接受客户端的消息
1.2若点击sent
那么就给指定的客户端发送消息
客户端因为不需要监听多个,所以只需要开启接收和发送线程就行,保证在接收的能进行发送就行。原理跟客户端的大同小异。
好了到了上代码环节
客户端
public class Serverfarme implements ActionListener{
ServerSocket server;
Socket socket1;
HashMap<String,Socket> myhashmap_keyst =new HashMap<String,Socket>();//有用给指定的客户端发消息
HashMap<Socket,String>myhashmap_keysk =new HashMap<Socket,String>();//根据客户端的来确定它的名字
static int socket_num=0;
Frame myframe = new Frame("sever");
Label lable1=new Label("port: ");
Label label2=new Label("say: ");
TextField tfport = new TextField(60);
TextField tfsay=new TextField(60);
Button btstart=new Button(" start ");
Button btsay=new Button(" send ");
Choice choice=new Choice();
TextArea ta = new TextArea(8,60);
Panel p1=new Panel();
Panel p2=new Panel();
void setmap() {//建立界面
p1.add(lable1); p1.add(tfport); p1.add(btstart);
choice.add("所有人");
p2.add(choice); p2.add(label2); p2.add(tfsay); p2.add(btsay);
myframe.add(p1,"North");
myframe.add(p2,"South");
myframe.add(ta,"Center");
myframe.pack();
myframe.setVisible(true);
btstart.addActionListener(this);
btsay.addActionListener(this);
}
public static void main(String[] args){
Serverfarme my=new Serverfarme();
my.setmap();
}
@Override
public void actionPerformed(ActionEvent e) {//实现Button的接口
Object source = e.getSource();
if(source == btstart) {//如果点击start按钮则启动接受客户端并收听的线程
listenreaderfirst st=new listenreaderfirst();
st.start();
}else{//点击发送按钮则启动发送线程
socket1=myhashmap_keyst.get(choice.getSelectedItem());//确定发消息给哪个客户端
listenwriter ww=new listenwriter(socket1);
ww.start();
}
}
class listenreaderfirst extends Thread{
@Override
public void run() {
boolean flag =true;
int post=Integer.parseInt(tfport.getText());
try {
server = new ServerSocket(post);
ta.append("Server starting..."+'\n');
while(flag) {//通过一直循环来等待客户端的连接
socket1 = server.accept();
socket_num++;
ta.append("Client connected from :"+socket_num+'\n');
String socketname="socket-"+socket_num;
choice.add(socketname);//在下拉框中添加选项
myhashmap_keyst.put(socketname, socket1);
myhashmap_keysk.put(socket1, socketname);
listenreader worker2=new listenreader(socket1);//读取客户端的信息
worker2.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class listenreader extends Thread{//读取客户端的信息
Socket s;
public listenreader(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
InputStream ir;
try {
ir = this.s.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(ir));
String tem=reader.readLine();
while(tem!=null) {
String sname=myhashmap_keysk.get(s);
ta.append(sname+": "+tem+'\n');
tem=reader.readLine();
}reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class listenwriter extends Thread{//向客户端发送信息
Socket s;
public listenwriter(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
OutputStream ioo;
try {
ioo = s.getOutputStream();
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(ioo));
String ss=tfsay.getText();
writer.write(ss);
writer.newLine();
writer.flush();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端
public class Client implements ActionListener{
Socket sr;
Frame myframe = new Frame("Client");
Label label1=new Label("port: ");
Label label2=new Label("say: ");
Label label3=new Label("IP: ");
TextField tfport = new TextField(30);
TextField tfsay=new TextField(60);
TextField tfip = new TextField(30);
Button btstart=new Button(" Connect ");
Button btsay=new Button(" Send ");
TextArea ta = new TextArea(8,60);
Panel p1=new Panel();
Panel p2=new Panel();
void setmap() {
p1.add(label3); p1.add(tfip); p1.add(label1); p1.add(tfport); p1.add(btstart);
p2.add(label2); p2.add(tfsay); p2.add(btsay);
myframe.add(p1,"North");
myframe.add(p2,"South");
myframe.add(ta,"Center");
myframe.pack();
myframe.setVisible(true);
btstart.addActionListener(this);;
btsay.addActionListener(this);
}
public static void main(String[] args) {
Client my=new Client();
my.setmap();
}
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
String tem_IP ;
int tem_Port ;
if (source == btstart) {
tem_IP = tfip.getText();
tem_Port = Integer.parseInt(tfport.getText());
try {
sr = new Socket(tem_IP.trim(), tem_Port);
ta.append("Connect to server…" + '\n');
clientreader rr=new clientreader(sr);
rr.start();
}catch (IOException ioException) {
ioException.printStackTrace();
}
} else {
clientwriter wr=new clientwriter(sr);
wr.start();
}
}
class clientreader extends Thread{
Socket s;
public clientreader(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
InputStream in;
try {
in = s.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
String ss = null;
ss=reader.readLine();
while(ss!=null) {
ta.append("Sever say: "+ss+'\n');
ss=reader.readLine();
ta.append(ss+'\n');
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class clientwriter extends Thread{
Socket s;
public clientwriter(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
OutputStream op;
try {
op = s.getOutputStream();
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(op));
String ss=tfsay.getText();
writer.write(ss);
writer.newLine();
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
有没有很神奇???