Java实现IO通信(服务器篇)
如何利用java实现我们的通信呢?首先我们了解一下什么是通信?通信的机制是怎样的?
首先来讨论一下什么是通信?通信,指人与人或人与自然之间通过某种行为或媒介进行的信息交流与传递,从广义上指需要信息的双方或多方在不违背各自意愿的情况下采用任意方法,任意媒质,将信息从某方准确安全地传送到另方。而这里所说的通信,是在同一局域网内,一个用户给其他用户发送信息的过程。
然后通行的机制是怎么样的呢?这里的JavaIO通信是这样的,首先我们需要一台服务器,并有一个或者多个用户。用户与用户之间传输信息就必须通过服务器,服务器的作用就是处理各种用户发来的信息,并作出各种执行各种指令。
最后来看一下如何通过代码实现我们简单的通信:
1.服务器:
1、首先我们需要一台服务器,我们可以用我们的电脑搭建服务器,怎么搭建呢?Java中提供了ServerSocket类,我可以使用这个类搭建服务器,在实例化这个类的时候需要指定一个端口(一般电脑上有256*256个端口,建议一般使用9000以上的端口,避免与一些热门端口冲突),而服务器的IP地址就是电脑所在局域网下的IP地址,值得注意的是,当我们电脑在不同局域网内是IP地址是会不同的!!!一般在命令行中使用ipconfig命令查看我们电脑的IP地址。关键代码:
public void createServer(int port){
try {
serverSocket=new ServerSocket(port);
} catch (IOException e){
e.printStackTrace();
}
}
2、服务器搭建好了以后,服务器接下来所需要做的就是等待用户接进服务器,才去做下一件事,否则一直等待用户上线。等待用户的客户端连接服务器是需要用到java提供的Socket类,这个类的作用,笔者解释为起到接口的作用,在这里我们只能用一台服务器,但是一台服务器却用多个接口,每一个接口可以连接一个用户,而服务器就可以管理所有的接口,以达到管理所有用户的目的
关键代码:
public void connect(){
Socket socket=serverSocket.accept();
当获取出来一个接口的时候,会用阻塞作用,会一直停留在在这里,直到有用户连接进服务器,才会执行下一条语句。
System.out.println("有一个客户机接入服务器");
}
3、现在我们最简单的服务器就搭建好了,可是这个服务器只有一个功能,就是让用户连接一下,然后就结束了。怎么让用户实时连接着不断开呢?很简单,我们只要用一个while(true)循环让程序不结束就可以了。接下来,再看看如何实现服务器读取用户的消息,和给用户发消息呢?首先我们需要IO流,之所以叫IO通信,就是这里的发送和读取信息都是通过IO流实现的。刚刚上面所说的一个服务器有多个接口,一个接口可以连接一个用户,现在我们就可以根据接口,获取出我们的IO流,同时值得注意的是一个接口获取出来的IO流只能读取和发送接口所对应接口连接的用户。比如:接口A连接的是A用户,所以由A接口获取的IO流只能读取A用户发来的信息,和对A用户发送信息。
关键代码:
while(true){
try {
Socket socket=serverSocket.accept();
System.out.println("有一个客户机接入服务器");
OutputStream output=socket.getOutputStream();//获取输出流,用于给用户发送信息
InputStream input=socket.getInputStream();//获取输入流,用户读取用户发来的信息
output.write("welcome!".getBytes());//给用户发送“welcome”
input.read();//读取用户消息的一个字节,调用一次读取一个字节,具有阻塞作用,如果用户没有发来消息,则会停留在这里,直到有消息发送过来。
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样我们的服务器就有了最基本的功能,用户连接进来后,服务器可以读取用户的信息,可以给用户发信息。但是仔细琢磨上面的代码或者执行它就会发现,这个服务器仅仅能对一个连接进来的用户发送和读取信息。这是为什么?来分析一下,首先用户执行进来就会执行Socket socket=serverSocket.accept();这行命令,为用户开辟接口,而到了 input.read();这句语句,假如用户一直没有向服务器发送消息,哪有程序就会阻塞在这句语句这里,而其他用户想要连接进来就得执行Socket socket=serverSocket.accept();这句语句,但是程序已经停留在input.read();这里了,这样就会出现只能连接进来一个用户。这也说明了主线程这能干一件事情,说到线程,我们应该怎么解决这样的问题呢,我们不可能只能有一个用户,那样达不到我们通信的目的。所以这里我们需要用到多线程来替我们解决这个问题。下面将会详细分析怎么解决这个问题。
既然我们的主线程只能做一件事情,那么我们就可以让服务器的信息读写放在一个子线程里,每一个用户由一个子线程用户信息的读取和发送,这个线程应该是具有该用户的所有信息,也称这个线程为接口线程,在服务器中可以通过一个接口线程间接访问所有的接口线程。关键代码:
ArrayList<Users> userList=new ArrayList<Users>();
while(true){
try {
Socket socket=serverSocket.accept();
System.out.println("有一个客户机接入服务器");
Users oneUser=new User(socket,userName, password);
userList.add(oneUser);
ChatManage chat=new ChatManage(socket,userName);//传一个socket过去用于信息的读写,再传一个用户名,用来标识聊天线程。用户名可以
由服务器指定,也可以由用户指定。
Chat.start();//启动线程。
} catch (IOException e) {
e.printStackTrace();
}
}
}
Public class ChatManage extends Thread{
Socket socket;
String userName;
Public ChatManage(Socket socket,String userName){
this.socket=socket;
this.userName=userName;
}
Public void run(){
While(true){
//获取IO流
InputStream input=socket.getInputStream ();
OuputStream output=socket.getOutputStream();
//后面就可以利用IO流读信息和发信息了,。。。。
}
}
}
为了更好地管理每一个连接进服务器的用户,我们可以为用户写一个用户类
每一个用户都保存在一个动态数组里。
public class Users {
String password;
String sex="man";
String account="123456";
String userName;
private Socket socket;
public Users(Socket socket,String userName,String password){
this.socket=socket;
this.userName=userName;
this.password=password;
}