客户端
package com.mtlk.chat;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
//implements是一个类实现一个接口用的关键字.实现一个接口,必须实现接口中的所有方法。
//在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口,
public class Client implements Runnable{
//定义一个socket套接字 s
private Socket s;
//抛出异常定义cilent方法
public Client() throws IOException{
//实例化s用来接收客户端的IP和端口,启动socket线程
s = new Socket("10.0.53.32",8888);
//定义具体的运算类
//Thread s = new Thread(this);
//s.start();
new Thread(this).start();
//接收服务器端的消息
receive();
}
private void receive() throws IOException{
//实例化sc 接收输入内容
Scanner sc = new Scanner(System.in);
//PrintWriter 包装字节/字符窜/文件流,实例化pw发送客户端的内容
PrintWriter pw = new PrintWriter(s.getOutputStream());
//true 一直获取输入信息
while (true){
//实例化mes接收sc中的输入内容
String mes = sc.next();
//如果输入了 end 就退出
if(mes.equalsIgnoreCase("end")){
System.out.println("退出");
return;
}
//pw.println(mes)把数据发送到文件,并换行
pw.println(mes);
//刷新
pw.flush();
}
}
//runnable 的run 方法
@Override
public void run() {
try{
//在Java中,能够读取一个字节序列的对象就称作一个输入流。
//读取客户端输入的东西 用is接收
InputStream is = s.getInputStream();
//实例化sc接收客户端的东西
Scanner sc = new Scanner(is);
//有东西就一直接收
while (true){
if(sc.hasNextLine())
System.out.println("Server:" + sc.nextLine());
}
} catch (IOException e) {
//在命令行打印异常信息在程序中出错的位置及原因
e.printStackTrace();
}
}
//启动client方法
public static void main(String[] args) throws IOException{
new Client();
}
}
服务器
package com.mtlk.chat;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
//使用implement类使用runnable方法
public class Server implements Runnable{
//建立一个服务端名为server的对象 ss
private ServerSocket ss;
private Socket s;
public Server() throws IOException {
//定义服务器端的接口 用ss接收
ss = new ServerSocket(8888);
//用s接收服务器端的输入内容
s = ss.accept();
new Thread(this).start();
receive();
}
private void receive() throws IOException {
//System.out.println("Server"+s.getInputStream());
//用 sc 接收服务器的输入内容
Scanner sc = new Scanner(System.in);
//用pw接收服务器要发送的东西
PrintWriter pw = new PrintWriter(s.getOutputStream());
while(true){
String mes = sc.next();
if(mes.equalsIgnoreCase("end")){
System.out.println("系统退出");
break;
}
pw.println(mes);
pw.flush();
}
}
@Override
public void run() {
try {
//读取服务器输入的内容用 s接收
InputStream is = s.getInputStream();
//用sc接收输入内容,方便打印
Scanner sc = new Scanner(is);
while(true){
if(sc.hasNextLine())
System.out.println("Client: " + sc.nextLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
new Server();
}
}
方法解释
implements
implements:是一个类实现一个接口用的关键字,实现一个接口,必须实现接口中的所有方法。
implements与Extends的区别
extends,表示对父类的继承,可以实现父类,也可以调用父类初始化 this.parent()。而且会覆盖父类定义的变量或者函数。
implements,表示对接口的实现,接口通过关键字interface 进行定义。eg:public class S implements F,在接口F中对方法进行声明,在类S中对该方法进行实现。
这两种实现的具体使用,是要看项目的实际情况,需要实现,不可以修改,用implements,只定义接口。需要具体实现,或者可以被修改,扩展性好,用extends。
implements是一个类实现一个接口用的关键字,他是用来实现接口中定义的抽象方法。
比如:people是一个接口,他里面有say这个方法。
public interface people()
{
public say();
}
但是接口没有方法体。
只能通过一个具体的类去实现其中的方法体。
比如chinese这个类,就实现了people这个接口。
public class chinese implements peopel{
public say()
{System.out.println("你好!");}
}
Runnable
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口
延伸
Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的
run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。
在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。
socket
所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口
要通过互联网进行通信,至少需要一对套接字,其中一个运行于客户端,我们称之为 Client Socket,另一个运行于服务器端,我们称之为 Server Socket。
Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
printwriter
PrintWriter()的作用是为了定义流输出的位置,并且此流可以正常的存储中文,减少乱码输出。此类实现在PrintStream中的所有 与PrintStream类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。 此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。