在tcp通信中,一般都是阻塞的,如果要实现非阻塞,我们可以使用多线程也可以使用nio中相关的类。这里我使用的是多线程的方式实现非阻塞。
服务器端:
1.创建ServerSocket对象,绑定监听端口;
2.调用accept()方法对客户端进行监听;
3.使用多线程对用户进行读操作,并反馈;
客户端:
1.创建Socket对象,通过IP和端口号和服务器进行连接;
2.分别使用多线程对服务器端进行读写操作;
代码如下:
服务器端:
package sency.one;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket ss;
private int port = 8000;
public Server() throws IOException {
// 创建接收端的ServerSocket
ss = new ServerSocket(port);
System.out.println("服务器启动!!!");
}
public static void main(String args[]) throws IOException {
new Server().service();
}
private void service() {
// TODO Auto-generated method stub
while (true) {
Socket socket = null;
try {
// 通过accept()方法进行监听,返回一个socket
socket = ss.accept();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
package sency.one;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket ss;
private int port = 8000;
public Server() throws IOException {
// 创建接收端的ServerSocket
ss = new ServerSocket(port);
System.out.println("服务器启动!!!");
}
public static void main(String args[]) throws IOException {
new Server().service();
}
private void service() {
// TODO Auto-generated method stub
while (true) {
Socket socket = null;
try {
// 通过accept()方法进行监听,返回一个socket
socket = ss.accept();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.writeUTF("Welcome!");
os.flush();
//输出客户端端口
if (socket.isConnected()) {
System.out.println("Port:" + socket.getPort());
}
// 采用多线程的方式处理
// 收信息线程
Thread receiveThread = new Thread(new ReHandler(socket));
receiveThread.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 收信息
class ReHandler implements Runnable {
private Socket socket = null;
public ReHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
printMsg(socket);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 在服务器端输出客户端发送的信息
private void printMsg(Socket socket) throws IOException {
DataInputStream is = new DataInputStream(socket.getInputStream());
String msg = "";
while ((msg = is.readUTF()) != null) {
System.out.println("来自:"+socket.getInetAddress()+"--"+socket.getPort());
System.out.println("#Client:" + msg);
if (msg.equals("bye")) {
break;
}
sendEcho(socket,msg);
}
is.close();
}
// 向客户端发送信息
private void sendEcho(Socket socket,String msg) throws IOException {
if(msg!=null){
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.writeUTF("#Server:收到"+msg);
os.flush();
}
}
}
客户端:
package sency.one;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client {
private Socket socket;
private String host = "localhost";
private int port = 8000;
public Client() throws IOException {
socket = new Socket(host, port);
System.out.println("客户端启动!!!");
System.out.println("Port:"+socket.getLocalPort());
}
public static void main(String args[]) throws IOException {
new Client().talk();
}
private void talk() {
// TODO Auto-generated method stub
// 采用多线程分别进行收发信息
// 发送线程
Thread sendThread = new Thread(new SendHandler());
sendThread.start();
// 收线程
Thread reThread = new Thread(new ReHandler());
reThread.start();
}
class SendHandler implements Runnable {
public void run() {
// TODO Auto-generated method stub
try {
sendMsg();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ReHandler implements Runnable {
public void run() {
// TODO Auto-generated method stub
try {
receiveMsg();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//发信息
public void sendMsg() throws IOException {
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
DataInputStream is = new DataInputStream(System.in);
String msg = null;
while ((msg = is.readLine()) != null) {
System.out.println("#Client:" + msg);
os.writeUTF(msg);
os.flush();
if(msg.equals("bye")){
break;
}
}
os.close();
is.close();
}
//收信息
private void receiveMsg() throws IOException{
DataInputStream is = new DataInputStream(socket.getInputStream());
String msg = null;
while((msg = is.readUTF())!=null){
System.out.println("#Service:"+msg);
if(msg.equals("bye")){
break;
}
}
is.close();
}
}
遇到的问题:
我不知道有没有人和我一样在读写的时候用了BufferedReader和BufferedWriter,以至于在后面使用readLine()方法时尽管是多线程也一直处于阻塞状态,我找了一下午,后来改成使用DataOutput/InputStream以及对应的readUTF()和writeUTF()方法,这个问题就解决了,具体原因我想了很久也没想明白,有个猜测不确定,等下周问了老师得到准确的答案再来说吧!!!
立个Flag:接下来有时间的话自己再用nio实现一下非阻塞通信,到时候来更博!