Java小项目—Socket实现的小小聊天室
socket使用TCP/IP协议来实现网络进程之间的通信,socket是TCP/IP的封装与应用,它不是协议,而是API。
实现目标:
①实现一个客户端与一个服务器之间的通信
②实现多个客户端与服务器之间的通信
③实现将用户的信息转发给所有的客户端
Client客户端:
package ChatRoom;
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;
/**
* 聊天室的客户端
* 1.完成连接服务器
* 2.给服务器发送信息或请求
*/
public class Client {
//Socket里封装了TCP协议
private Socket socket;//设置属性私有化
//设置构造器用来初始化:与类同名没有返回值
public Client() throws UnknownHostException, IOException{
/*
* 实例化Socket的过程就是连接远端计算机的过程
* new Socket(访问的IP,服务器的端口号);
* 过程,这里需要传入两个参数
* 参数1:服务端的IP地址信息
* 参数2:服务端的端口
* 通过IP可以找到服务端的计算机,
* 通过端口可以连接到运行在服务端计算机上的服务端应用程序。
*/
System.out.println("正在连接服务器.....");
socket=new Socket("localhost",8088);
System.out.println("已经连接成功服务器");
}
//创建客户端工作方法:
public void start(){
//1.实现客户端向服务器端发送请求/信息的功能
//输出
try {
//发信息给服务器
OutputStream out=socket.getOutputStream();
//设置编码格式(UTF-8 GBK) 说明我们设置的流
OutputStreamWriter osw=new OutputStreamWriter(out,"utf-8");
//设置输出格式:
PrintWriter pw=new PrintWriter(osw,true);
//正式输出:`
pw.println("你好,服务器");
Scanner scan=new Scanner(System.in);
while(true){
pw.println(scan.nextLine());
if(scan.nextLine() == "over") {
break;
}
}
//如果需要接受服务器的信息先关闭资源socket.shutdownOutput()
//然后写从服务器接收到的信息类似于客户端接受服务器信息一样
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//必须执行
}
}
public static void main(String[] args) {
try {
Client c=new Client();
c.start();
} catch (UnknownHostException e) {
System.out.println(1);
e.printStackTrace();
} catch (IOException e) {
System.out.println(2);
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Server服务器端:
package ChatRoom;
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.ArrayList;
import java.util.List;
/**
* 聊天室的服务器端
* 1.设置端口号
* 2.接收客户端发送的信息或要求
*/
public class Server {
private static final String ClientHandler = null;
/*
* 运行在服务端ServerSocket两个作用:
* 1:申请服务端口,客户端就是通过该端口
* 与服务端建立连接的
* 2:监听申请的服务端口,一旦一个客户端
* 通过该端口与服务端连接,ServerSocket
* 就会主动创建一个Socket与该客户端通讯
*/
private ServerSocket server;
//储存客户端所有数据:
List<PrintWriter> list;
//创建构造器用来初始化server:
public Server() throws IOException{
/*
* 初始化ServerSocket的同时,指定
* 要申请的服务端口,若该端口已经
* 被其他程序占用,会抛出异常。
*/
//server=new ServerSocket("你要申请的端口号");
server=new ServerSocket(8088);
list=new ArrayList<PrintWriter>();
}
//聊天开始的方法:用于接收客户端发送消息
public void start() throws IOException{
/* 监听端口,等待客户端连接
* ServerSocket的accept方法
* 是一个阻塞方法,作用是监听
* 服务端口,直到一个客户端通过
* 该端口连接,才会返回一个Socket
* 实例,通过这个Socket可以与刚
* 连接的客户端通讯。
* accept:接收客户的连接及请求
*/
System.out.println("等待客户端连接...");
Socket socket=server.accept();
//调用线程类-----处理客户端发送来的信息
//1.创建对象:
ServerHandle handle=new ServerHandle(socket);
//调用------启动一个线程完成对该客户端的交互:
new Thread(handle).start();//这个就由你们自己测试了,可以用朋友的电脑也连接这个服务器进行测试
System.out.println("连接一个客户端");
//接受客户端
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"UTF-8");
BufferedReader br = new BufferedReader(isr);
System.out.println("客户端说:"+br.readLine());
while (true) {
System.out.println("客户端说:"+br.readLine());
if(br.readLine() == "over") {
break;
}
}
//如果需要发信息给客户端先关闭资源socket.shutdownOutput()
//类似于客户端发信息给服务器端一样
}
public static void main(String[] args) {
//创建一个Server对象:
try {
Server s=new Server();
s.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//创建一个内部类:定义输出流,数组用来存储用户发送的信息
//因为集合问题(list)无法再其他类中被调用,所以无法实现向集合中添加用户传入的信息
//所以在Server里再声明一个内部类
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket=socket;
}
@Override
public void run() {
PrintWriter pw=null;
try {
OutputStream out=socket.getOutputStream();
//设置编码格式(UTF-8 GBK) 说明我们设置的流
OutputStreamWriter osw=new OutputStreamWriter(out,"utf-8");
//设置输出格式:
pw=new PrintWriter(osw);
list.add(pw);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
//创建线程-----处理各个客户端的请求
class ServerHandle extends Thread{
private Socket socket;
//初始化:
public ServerHandle(Socket socket) throws IOException{
this.socket=socket;
//将参数赋值给本类对象
}
@Override
public void run() {
//接收用户信息:
InputStream in;
try {
in = socket.getInputStream();
//设置接收的流的编码格式
InputStreamReader isr=new InputStreamReader(in,"UTF-8");
//设置接收,将用户输出流转换
BufferedReader br=new BufferedReader(isr);
//将接收的内容输出到控制台中 readLine:读取一行
while(true){
System.out.println("客户端说:"+br.readLine());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}