Netty学习之一–Java socket编程(单线程+多线程)

  • Post author:
  • Post category:java




1. Socket 通信简介及模型

Java Socket 可实现客户端–服务器间的双向实时通信。

java.net包

中定义的两个类

socket和ServerSocket

,分别用来实现双向连接的client和server端。



1.1




重要的Socket API:






  1. Accept

    方法用于产生”阻塞”




    ,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续




  2. GetInputStream

    方法获得网络连接输入




    ,同时返回一个InputStream对象实例。




  3. GetOutputStream

    方法连接的另一端将得到输入




    ,同时返回一个OutputStream对象实例。





2. Socket 通信实现方法



2.1  服务器端(单线程)



  1. 实例化SeverSocket对象。
  2. 调用ServerSocket的accept()方法,生成socket对象,监听从端口上发来的连接请求,

    等待连接期间会造成阻塞,

  3. 根据生成的客户端的Socket对象,进行读写IO操作。
  4. 关闭打开的流和Socket对象。

2.2  客户端


  1. 连接客户端指定IP端口,实例化socket对象。
  2. 根据生成socket对象,进行读写IO操作。
  3. 关闭打开的流和Socket对象。



2.3 服务器端 (多线程)

  1. 实例化SeverSocket对象,循环调用accept()等待客户端连接
  2. 客户端创建一个socket并请求和服务器端连接
  3. 服务器端接受客户端请求,创建socket与该客户建立专线连接
  4. 建立连接的两个socket在一个单独的线程上对话
  5. 服务器端继续等待新的连接









PS:多线程下服务器发送数据,客户端争抢服务器资源











服务器代码(单线程/单客户端)








import

java.io.BufferedReader;


import

java.io.IOException;


import

java.io.InputStreamReader;


import

java.io.PrintWriter;


import

java.net.ServerSocket;


import

java.net.Socket;


public


class

SocketService {




//搭建服务器端



public


static


void

main(String[] args)

throws

IOException{


SocketService socketService =

new

SocketService();


//1、a)创建一个服务器端Socket,即SocketService


socketService.oneServer();

}


public


void

oneServer(){



try

{


ServerSocket server=

null

;


try

{


server=

new

ServerSocket(3900);


//b)指定绑定的端口,并监听此端口。


System.


out


.println(

“服务器启动成功”

);


//创建一个ServerSocket在端口3900监听客户请求


}

catch

(Exception e) {


System.


out


.println(

“没有启动监听:”

+e);


//出错,打印出错信息


}

Socket socket=

null

;


try

{


socket=server.accept();


//2、调用accept()方法开始监听,等待客户端的连接



//使用accept()阻塞等待客户请求,有客户



//请求到来则产生一个Socket对象,并继续执行


}

catch

(Exception e) {


System.


out


.println(

“Error.”

+e);


//出错,打印出错信息


}


//3、获取输入流,并读取客户端信息


String line;

BufferedReader in=

new

BufferedReader(

new

InputStreamReader(socket.getInputStream()));


//由Socket对象得到输入流,并构造相应的BufferedReader对象


PrintWriter writer=

new

PrintWriter(socket.getOutputStream());


//由Socket对象得到输出流,并构造PrintWriter对象


BufferedReader br=

new

BufferedReader(

new

InputStreamReader(System.


in


));


//由系统标准输入设备构造BufferedReader对象


System.


out


.println(

“Client:”

+in.readLine());


//在标准输出上打印从客户端读入的字符串


line=br.readLine();


//从标准输入读入一字符串



//4、获取输出流,响应客户端的请求



while

(!line.equals(

“end”

)){



//如果该字符串为 “bye”,则停止循环


writer.println(line);


//向客户端输出该字符串


writer.flush();


//刷新输出流,使Client马上收到该字符串


System.


out


.println(

“Server:”

+line);


//在系统标准输出上打印读入的字符串


System.


out


.println(

“Client:”

+in.readLine());


//从Client读入一字符串,并打印到标准输出上


line=br.readLine();


//从系统标准输入读入一字符串


}

//继续循环



//5、关闭资源


writer.close();

//关闭Socket输出流


in.close();

//关闭Socket输入流


socket.close();

//关闭Socket


server.close();

//关闭ServerSocket


}

catch

(Exception e) {


//出错,打印出错信息


System.


out


.println(

“Error.”

+e);

}

}


}











客户端代码






import

java.io.BufferedReader;


import

java.io.IOException;


import

java.io.InputStream;


import

java.io.InputStreamReader;


import

java.io.PrintWriter;


import

java.net.InetAddress;


import

java.net.Socket;


import

java.net.URL;


public


class

SocketClient {




// 搭建客户端



public


static


void

main(String[] args)

throws

IOException {



try

{



// 1、创建客户端Socket,指定服务器地址和端口


Socket socket=

new

Socket(

“127.0.0.1”

,3900);

System.


out


.println(

“客户端启动成功”

);


// 2、获取输出流,向服务器端发送信息



// 向本机的3900端口发出客户请求


BufferedReader br =

new

BufferedReader(

new

InputStreamReader(System.


in


));


// 构造BufferedReader对象


PrintWriter write =

new

PrintWriter(socket.getOutputStream());


// 由Socket对象得到输出流,并构造PrintWriter对象



//3、获取输入流,并读取服务器端的响应信息


BufferedReader in =

new

BufferedReader(

new

InputStreamReader(socket.getInputStream()));


// 由Socket对象得到输入流,并构造相应的BufferedReader对象


String readline;

readline = br.readLine();

// 从系统标准输入读入一字符串



while

(!readline.equals(

“end”

)) {



// 若从标准输入读入的字符串为 “end”则停止循环


write.println(readline);


// 将从系统标准输入读入的字符串输出到Server


write.flush();


// 刷新输出流,使Server马上收到该字符串


System.


out


.println(

“Client:”

+ readline);


// 在系统标准输出上打印读入的字符串


System.


out


.println(

“Server:”

+ in.readLine());


// 从Server读入一字符串,并打印到标准输出上


readline = br.readLine();

// 从系统标准输入读入一字符串


}

// 继续循环



//4、关闭资源


write.close();

// 关闭Socket输出流


in.close();

// 关闭Socket输入流


socket.close();

// 关闭Socket


}

catch

(Exception e) {


System.


out


.println(

“can not listen to:”

+ e);

// 出错,打印出错信息


}

}


}


服务器代码(多线程/多客户端)




import

java.io.BufferedReader;


import

java.io.IOException;


import

java.io.InputStreamReader;


import

java.io.PrintWriter;


import

java.net.ServerSocket;


import

java.net.Socket;


public


class

SocketService {




// 搭建服务器端



public


static


void

main(String[] args)

throws

IOException {


SocketService socketService =

new

SocketService();


// 1、a)创建一个服务器端Socket,即SocketService


socketService.oneServer();

}


public


void

oneServer() {



try

{


ServerSocket server =

null

;


try

{


server =

new

ServerSocket(3900);


// b)指定绑定的端口,并监听此端口。


System.


out


.println(

“服务器启动成功”

);


// 创建一个ServerSocket在端口3900监听客户请求


}

catch

(Exception e) {


System.


out


.println(

“没有启动监听:”

+ e);


// 出错,打印出错信息


}

Socket socket =

null

;


int

i = 0;


int

count = 100;

// 限制最大连接为100



while

(i++ < count) {



try

{


socket = server.accept();

System.


out


.println(

“当前连接数量:”

+ i);


// 2、调用accept()方法开始监听,等待客户端的连接



// 使用accept()阻塞等待客户请求,有客户



// 请求到来则产生一个Socket对象,并继续执行


Handler handler =

new

Handler(socket, i);


new

Thread(handler).start();

}

catch

(Exception e) {


System.


out


.println(

“Error.”

+ e);


// 出错,打印出错信息


}

}

server.close();

// 关闭ServerSocket


}

catch

(Exception e) {


// 出错,打印出错信息


System.


out


.println(

“Error.”

+ e);

}

}

}

class

Handler

implements

Runnable {




private

Socket

socket

;


private


int


i

;


public

Handler(Socket socket,

int

i) {



this

.

socket

= socket;


this

.

i

= i;

}


public


void

run() {


BufferedReader in =

null

;

PrintWriter writer =

null

;

BufferedReader br =

null

;


try

{



// 3、获取输入流,并读取客户端信息


String line;

in =

new

BufferedReader(

new

InputStreamReader(


socket

.getInputStream()));


// 由Socket对象得到输入流,并构造相应的BufferedReader对象


writer =

new

PrintWriter(

socket

.getOutputStream());


// 由Socket对象得到输出流,并构造PrintWriter对象


br =

new

BufferedReader(

new

InputStreamReader(System.


in


));


// 由系统标准输入设备构造BufferedReader对象


System.


out


.println(

“Client:”

+

i

+

“:”

+ in.readLine());


// 在标准输出上打印从客户端读入的字符串


line = br.readLine();


// 从标准输入读入一字符串



// 4、获取输出流,响应客户端的请求



while

(!line.equals(

“end”

)) {



// 如果该字符串为 “bye”,则停止循环


writer.println(line);


// 向客户端输出该字符串


writer.flush();


// 刷新输出流,使Client马上收到该字符串


System.


out


.println(

“Server:”

+ line);


// 在系统标准输出上打印读入的字符串


System.


out


.println(

“Client”

+

i

+

“:”

+ in.readLine());


// 从Client读入一字符串,并打印到标准输出上


line = br.readLine();


// 从系统标准输入读入一字符串


}

// 继续循环


}

catch

(Exception e) {


System.


out


.println(

“Error.”

+ e);


// 出错,打印出错信息


}

finally

{



// 5、关闭资源



try

{


writer.close();

// 关闭Socket输出流


in.close();


socket

.close();

// 关闭Socket


}

catch

(IOException e) {


System.


out


.println(

“Error.”

+ e);


// 出错,打印出错信息


}

// 关闭Socket输入流


}

}


}



















版权声明:本文为xhzhujin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。