Socket编程实现客户端与服务器一对一聊天
Socket(套接字)
使用Socket编程实现数据的交互需要经历以下几个步骤:
1、创建Socket:
Socket socket = new Socket("host",port);
2、打开IO流
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);//输出流
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))//输入流
注: socket属于服务器,那么socket的方法getOutputStream就是向客户端输出数据,getInputStream获取客户端传过来的数据
3、进行数据的交互
out.print() in.read();
4、关闭Socket
socket.close();
服务端跟客户端有所不同,客户端只要创建socket并且请求服务器连接connect,服务器创建完socket使用ServerSocket.accept()方法
阻塞程序直到收到了来自客户端的请求,接收到来自客户端的socket继续往下执行。
其中客户端代码如下:
import java.net.*;
import java.io.*;
public class Client
{
boolean flag = false;//当遇到客户端输入bye取消与服务端连接的标识
public Client(){
try{
Socket socket =new Socket("127.0.0.1",4800);//(host,port)
System.out.println("客户端已经开启----");
new Thread(new Output(socket)).start();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//获取来自服务端的信息
String str = in.readLine();//读取信息
while(!str.equals("bye")) {
System.out.println("服务端:"+str);
str = in.readLine();//当in每次调用readLine方法就会往下读取一行,慎用
}
in.close();
if (flag==true){
socket.close();
}
}
catch(Exception e){
e.printStackTrace();
}
}
//当客户端没有写入信息的时候需要写一个线程来实现写操作,不然程序就会被卡在readLine一直获取键盘信息
class Output implements Runnable{
Socket socket;
public Output(Socket socket){
this.socket = socket;
}
public void run(){
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
String str = br.readLine();
while(!str.equals("bye")) {
System.out.println("客户端:"+str);
out.print(str+"\n");//从键盘没有获取到回车按键,需要加\n判断一次输入为一行
out.flush();
str = br.readLine();
if (str.equals("bye")) {
flag = true;
}
}
br.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
new Client();
}
}
服务端代码如下:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
boolean flag = false;
public Server(){
try {
ServerSocket serverSocket = new ServerSocket(4800);
System.out.println("服务端正在等待客户端请求......");
Socket socket = serverSocket.accept();//一直等待客户端的请求
System.out.println("connect success");
new Thread(new Output(socket)).start();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
/* int i = 0;
while ((i = in.read()) != 0){
System.out.println(i);
}*/
String str = in.readLine();
while(!str.equals("bye")) {
System.out.println("客户端:" + str);
str = in.readLine();
}
in.close();
if (flag==true) {
socket.close();
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class Output implements Runnable{
Socket socket;
public Output(Socket socket){
this.socket = socket;
}
public void run(){
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
String str = br.readLine();
while(!str.equals("bye")) {
System.out.println("服务端:"+str);
out.print(str+"\n");
out.flush();
str = br.readLine();
if (str.equals("bye")) {
flag = true;
}
}
br.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server();
}
}
总结
今天使用socket来实现客户端与服务端的通信功能,遇到了很多问题,其中一个比较严重的就是没有将写操作放入线程中进行,导致程序没有输出信息,第二个问题是当获取到从客户端/服务端来的信息时候,我是一行行的进行读取,但是没有读取到回车按键,无法区分一行的信息,导致客户端输入的信息,服务端无法接收,在朋友的debug下,使用了以下这个方法调试是否有数据传到另一边:
int i = 0;
while ((i = in.read()) != 0){
System.out.println(i);
使用BufferReader的read方法返回的ASCII码,强转为int 可以直接获取原来的值(在ASCII范围内的值)。

浙公网安备 33010602011771号