Socket通信是基于TCP/IP协议的一种进程间通信方式, 通过指定IP地址和端口号进行客户端与服务器的连接完成通信,使用Socket编程时的步骤如下:
服务器端:
第1步.实例化监听套接字,并指定端口号:
//一台服务器默认端口号有256*256,其中1~1023是公认端口号,1024~65535可以自定义作用;
ServerSocket server = new ServerSocket(9999);
第2步.调用accept()等待客户端连接,如果没有客户端进行连接,此方法一直处于阻塞状态,直到有客户端连接,接触阻塞并返回套接字:
Socket socket = server.accept();
第3步. 使用流进根据套接字得到输入输出流进行通信:
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
第4步.关闭套接字、流资源:
socket.close;
is.close();
os.close();
客户端:
第1步.实例化套接字,并指定服务器地址和端口:
Socket socket = new Socket("127.0.0.1",9999);
第2步.使用流进根据套接字得到输入输出流进行通信:
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
第3步. 关闭套接字、流资源:
socket.close;
is.close();
os.close();
其中难点就在使用流进行传输,当我使用缓冲流BufferedReader和BufferedWriter时,代码如下:
//客户端中向服务器写入数据的流
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//服务器中读取客户端数据的流
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((content=reader.readLine())!=null){
if(content.equals("over")){
System.out.println(hostName+"已下线!");
break;
}
StringBuffer buffer = new StringBuffer(content);
writer.println(buffer.reverse().toString());
System.out.println(hostName+"说:"+content);
}
此时readLine()一直处于阻塞状态,读取不到数据,这是因为readLine()用于读取一行数据,通过换行符来判断,在一般操作中通过控制台输入数据,是可以读取到的,但是在Socket中没有提供换行符,因此一直处于阻塞状态。
解决办法:
第一种:通过BufferedWriter的newLine()写入一个分隔符,之后采用flush()刷新:
writer.write(String);
writer.newLine();
writer.flush();
第二种:采用打印流PrintWriter代替BufferedWriter,不过要注意,PrinterWriter刷新缓冲区的操作,如下:
//实例化PrintWriter实例,true表示启用了自动刷新,但只有调用println()、format()、printf()时才能自动刷新
writer = new PrintWriter(socket.getOutputStream(),true);
writer.println(String);
下面是用Socket编程实现多人聊天代码:
客户端:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket socket =null;
try {
//1.实例化监听套接字
ServerSocket server = new ServerSocket(1994);
/**
* 根据监听套接字获取套接字,当每有一个客户端连接服务器时,开启一个子线程进行通讯,
* 将通讯交给子线程完成
*/
while(true){
socket = server.accept();
new Thread(new Service(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
子线程中处理通讯的类:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Service implements Runnable{
private Socket socket;
private String hostName;
private BufferedReader reader;
private PrintWriter writer;
public Service(Socket socket) {
super();
this.socket = socket;
//通过socket获取客户端主机名
hostName = socket.getInetAddress().getHostName();
try {
//读取客户端消息
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//给客户端发送消息
writer = new PrintWriter(socket.getOutputStream(),true);
System.out.println(hostName+"已上线!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
// TODO Auto-generated method stub
String content = null;
try {
while((content=reader.readLine())!=null){
if(content.equals("over")){
System.out.println(hostName+"已下线!");
break;
}
StringBuffer buffer = new StringBuffer(content);
writer.println(buffer.reverse().toString());
System.out.println(hostName+"说:"+content);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(reader != null){
reader.close();
reader = null;
}
if(socket != null){
socket.close();
socket = null;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
客户端:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
/**
* @param args
*/
private static BufferedWriter writer;
private static BufferedReader reader_keyboard,readr_fromServer;
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket socket = null;
try {
//1.实例化套接字,并指定主机地址和端口号
socket = new Socket(InetAddress.getLocalHost(), 1994);
//向服务器写入数据的流
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//接收从键盘输入的数据
reader_keyboard = new BufferedReader(new InputStreamReader(System.in));
readr_fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String content = null;
String contentFromServer = null;
do{
System.out.println("请输入信息:");
content = reader_keyboard.readLine();
if(content.equals("over")){
break;
}
writer.write(content);
writer.newLine();
writer.flush();
contentFromServer = readr_fromServer.readLine();
if(contentFromServer!=null){
System.out.println("服务器:"+contentFromServer);
}
}while(true);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(reader_keyboard != null){
reader_keyboard.close();
reader_keyboard = null;
}
if(socket != null){
socket.close();
socket = null;
}
if(writer != null){
writer.close();
writer = null;
}
} catch (IOException e) {
// TODO: handle exception
}
}
}
}
转载请注明原文地址: https://ju.6miu.com/read-664899.html