JAVA套接字实现简易的双人通信系统
JAVA套接字资料
socket是基于应用服务与TCP/IP通信之间的一个抽象,他将TCP/IP协议里面复杂的通信逻辑进行分装,对用户来说,只要通过一组简单的API就可以实现网络的连接。借用网络上一组socket通信图给大家进行详细讲解:
首先,服务端初始化ServerSocket,然后对指定的端口进行绑定,接着对端口及进行监听,通过调用accept方法阻塞,此时,如果客户端有一个socket连接到服务端,那么服务端通过监听和accept方法可以与客户端进行连接。
以上资料:
解决方案
综上所述,JAVA套接字需要一个SeverSocket对象作为服务端,监听Socket的连接请求,需要一个Socket对象作为客户端,向SeverSocket发送连接的请求。客户端和服务端建立连接后为全双工,两端均可接收和发送数据,接收和发送可以用流来实现。所以用SeverSocket和Socket分别作为两端进行通信。
但是如果两端仅仅用while循环来不停的发送和接收数据会发生阻塞,原因是因为一端只有完成发送操作后,才能开始接收操作,而键盘读取字符串的函数是阻塞的,socket流的读操作也会发生阻塞,所以只有键盘输入并按下回车,程序才会继续执行,另一端也相同。最终造成的结果是两端每次只能说一句话,说完后必须等待,只有接收到对方发来信息后,才可也说下一句。
解决方法就是利用多线程,服务端和客户端都设置两个线程,一个线程专门用来接收信息,一个专门用来发送信息。这样,接收和发送互不影响,消除阻塞。
主要代码块
服务端,接收客户端的连接请求,创建新的线程:
客户端,请求连接,并创建新的线程:
接收的线程:不断从输入流读取数据并打印
发送的线程:不断从键盘读取字符串并写入输出流
客户端和服务端的接收和发送进程基本相同
运行结果
最终代码
服务端
package com;
import java.io.IOException;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Server{
static ServerSocket serverSocket;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(1515);
while(true) {
Socket accept_client = serverSocket.accept();
new Thread(new ServerIn(accept_client)).start();
new Thread(new ServerOut(accept_client)).start();
}
} catch (IOException e) {
e.printStackTrace();
try {
serverSocket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
//接受的线程
class ServerIn implements Runnable{
Socket socket;
ServerIn(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
while(true) {
byte infile[] = new byte[1024];
int size = in.read(infile);
String string = new String(infile,0,size);
if(!string.equals("") && !string.equals("\n")) System.out.println("message from client: "+ string);
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
//发送的线程
class ServerOut implements Runnable{
Socket socket;
Scanner reader = new Scanner(System.in);
ServerOut(Socket socket){
this.socket = socket;
}
public void run() {
try {
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
while(true) {
String string = reader.nextLine();
out.write(string);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
客户端
package com;
import java.io.*;
import java.util.*;
import java.net.*;
public class Client{
public static void main(String[] args) {
try {
Socket client = new Socket("127.0.0.1",1515);
new Thread(new ClientIn(client)).start();
new Thread(new ClientOut(client)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接受的线程
class ClientIn implements Runnable{
Socket socket;
ClientIn(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
while(true) {
byte infile[] = new byte[1024];
int size = in.read(infile);
String string = new String(infile,0,size);
if(!string.equals("") && !string.equals("\n")) System.out.println("message from server: "+ string);
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
//发送的线程
class ClientOut implements Runnable{
Socket socket;
Scanner reader = new Scanner(System.in);
ClientOut(Socket socket){
this.socket = socket;
}
public void run() {
try {
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
while(true) {
String string = reader.nextLine();
out.write(string);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
计算1913 李文轩