上一次实现了客户端和服务端互相交互对话z甚至传输文件,这次需要实现的是客户端和客户端对话交互,需要明确的是客户端和服务端都要干什么,下面总结一下他们各自都要干什么。
服务端
1.持续监听一个端口。只有监听到一个端口后,才能得到一个socket(套接字)
2.如果监听到一个客户端请求,就开一个线程,每开一个线程就将其存入一个vector动态数组
3.线程要实现一些功能,包括,1.显示客户端发来了什么消息,并存入
2.循环遍历要发给哪个客户端
3.将保存的信息发个要发给的哪个客户端
客户端
1.发送消息,从键盘写入消息后,将其送入套接字的输出流;要用循环,有什么些什么,一直写
2.接收消息,接收从服务端发来的任一客户端的消息;要用循环,来什么显示什么;
3.为了实现一直双向交互吗,开两个线程,一个用来接收消息,一个用来发送消息;
多说无益,上代码,内容更清晰
首先是服务端;
package LastChat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
public class TcpServerSocket
{
//可以并发处理多个客户端连接
public static void main(String[] args) {
//动态数组保存进入的客户端;
Vector ClientVector = new Vector<>();
// TODO Auto-generated method stub
try {
//监听某个特定的的端口
System.out.println("监听端口ing。。。");
ServerSocket ss = new ServerSocket(8888);
//实现循环监听
while(true){
//获得客户端的连接
Socket s = ss.accept(); //accept()方法会阻塞直到客户端连入
System.out.println("获得客户端连接");
//socket对象是对端的存根
System.out.println("socket远程地址 " + s.getRemoteSocketAddress());
System.out.println("socket本地地址" + s.getLocalSocketAddress());
//在新的线程里面处理Socket
ServerThread thread = new ServerThread(s,ClientVector);
//开启线程;
thread.start();
//将线程加入动态数组;
ClientVector.add(thread);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//线程类
class ServerThread extends Thread
{
Socket s;
Vector vector = new Vector<>();
//创建读缓冲区
BufferedReader in;
//创建写入字符流
PrintWriter out;
//构造方法,传入套接字和动态数组;
public ServerThread(Socket s, Vector vector) throws IOException
{
super();
this.s = s;
this.vector = vector;
//输入流和输出流;
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
}
public void send (String line,ServerThread t)
{
for(ServerThread st : vector) //遍历动态数组中所有线程
{
if(st!=t) //如果动态数组里的线程和发送的客户端不是一个,就发送消息;
{
st.sendmessage(line);
}
}
}
//发送消息的方法;
public void sendmessage(String line) {
out.println(line);
out.flush();
}
@Override
public void run() {
try {
while (true)
{
String line ;
//如果输入不空,就读入,并发送到其他客户端;
if((line =in.readLine())!=null)
{
System.out.println("获得客户端输入"+line);
line = s.getRemoteSocketAddress().toString()+"说了"+line;
//群发到其他客户端
send(line,this);
}
}
//s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
其次是客户端;
package LastChat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class TcpClientSocket {
public static void main(String[] args)
{
try
{
new TcpClientSocket();
} catch (Exception e)
{
// TODO: handle exception
}
}
Socket s;
BufferedReader in ;
PrintWriter out;
public TcpClientSocket() throws UnknownHostException, IOException
{
s = new Socket("localhost", 8888);
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
//开启新线程读取控制台输入,并发送给服务端;
new ReadSystemInThread().start();
//开启新线程获得服务端输入并显示;
new ReadServerInThread().start();
}
class ReadSystemInThread extends Thread
{
public void run()
{
//从客户端输入要说的话;
Scanner scanner = new Scanner(System.in);
System.out.println("请输入客户端要说的话");
//循环输入;
while(true)
{
String line = scanner.nextLine();
//将输入的话写入socket的输出流;
out.println(line);
//刷新缓冲区;
out.flush();
}
}
}
class ReadServerInThread extends Thread
{
public void run()
{
while(true)
{
String line;
try {
if((line = in.readLine())!=null)
{
System.out.println("收到的信息是:"+line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
这应该是最简洁的实现方式了。