Socket 服务器和客户端连接

来源:转载

这2天,看了看网路编程,这里记录一下自己的理解。

网络编程,简单的理解,就是通讯,这里说服务器和客户端的通讯。服务器一直监听着,看是不是有客户来访问。

服务器:相当于一个家,或者一个定点买东西的地方,肯定是需要地址的,不然别人找不到地方对吧。

JAVA 体面提供了InetAddress 对象,通过getByName 等方法,可以获取地址(住址名称)的。

客户端:客户嘛,大家都明白,就是要去和服务器进行回话,相当于我要和你联系,需要你家住址(起码要电话号码之类的,才能找到你)。

地址和端口:地址就不说了,就是能确定你位置一个东东。因为一台服务器,可能有很多服务,这里需要用端口来区分。好比:我到你家买东西,8080 这个端口卖饼干,8081 端口可以卖水果等等。

交互:我作为客户,想到你家买东西,那么我肯定要知道你家地址,我只买饼干,那么我还要知道你家饼干的端口8080.你作为服务器,也就是卖住,你不知道什么人来买,因此你只需要将卖饼干 和买水果的端口打开,派人看着(监听)就行。

JAVA 给我们节省了很多,对于服务器,只需要用ServerSocket 监听端口,有人访问之后有accept()进行允许就行了。对于客户,要用Socket 传入地址(Address) 和端口(PORT)知道你 去哪,买什么。

当然,两边都有了, 当我有地址 有 端口,对你进行访问的时候,肯定得有通道吧,以前可以走路 坐车。现在起码也要卫星信号,才能电话连接对吧。JAVA 这里用了InputStream 和OutputStream ,可以用(Reader 和Writer),通过getInputStream (),getOutputStream ().获得,这就是双方的一个联系通道。

下面我来看看一个简单的程序:

Server 服务器端:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class MyServer {public static final int PORT = 8080;public static void main(String[] args) throws IOException, InterruptedException {// 服务器现监听一个端口ServerSocket ss = new ServerSocket(PORT);// 如果同一人访问,就给他开门Socket s = ss.accept();try{// 获取双方的传输通道BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));// 这里注意 有个true,表示自动刷新缓冲区// 如果没有这个,他们就会一直等待信息,没有一行信息就无法进行下面的操作,一直会等到缓冲区满// 因此用刷新功能,将信息通过网络发送出去,客户端那边一样,信息需要通过网络交互PrintWriter out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()),true);while(true){// 获取客户端来的消息,"END" 就退出String str = in.readLine();if("END".equals(str)){break;}System.out.println("str is :"+str);out.println(str);Thread.currentThread().sleep(1000);}}finally{// 这里为了节省资源,都关闭s.close();ss.close();}}}

Client 客户端:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;public class MyClient {public static void main(String[] args) throws IOException {// 地址,null 表示本地127.0.0.1InetAddress addr = InetAddress.getByName(null);// 需要的端口Socket socket = new Socket(addr, 8080);try {System.out.println("socket = " + socket);BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 自动刷新PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);// 我假设 说十句话for (int i = 0; i < 10; i++) {out.println("hello :" + i);String str = in.readLine();System.out.println(str);}out.println("END");} finally {socket.close();}}}

那么同理,我们只需修改一点,就可以完成多个客户端的访问,当然不是并发,这里用了点线程

服务器端线程

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;public class ServerThread extends Thread {private Socket socket;private BufferedReader in;private PrintWriter out;// 服务器端的构造器,需要套接字socketpublic ServerThread(Socket s) throws IOException {socket = s;in = new BufferedReader(new InputStreamReader(socket.getInputStream()));out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);// 启动run start();}public void run() {String str;try {while (true) {str = in.readLine();if ("END".equals(str)) {break;}System.out.println("Str is :" + str);out.println(str);}System.out.println("closing...");} catch (IOException e) {e.printStackTrace();}finally{try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}

客户端线程

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;public class ClientThread extends Thread {private Socket socket;private BufferedReader in;private PrintWriter out;private static int counter = 0;private int id = counter++;private static int threadcount = 0;public static int getThreadCount() {return threadcount;}// 客户端的构造,需要地址public ClientThread(InetAddress addr) {System.out.println("client is :" + id);threadcount++;try {socket = new Socket(addr, 8080);} catch (IOException e) {e.printStackTrace();}try {in = new BufferedReader(new InputStreamReader(socket.getInputStream()));out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);start();} catch (IOException e) {try {socket.close();} catch (IOException e1) {e1.printStackTrace();}e.printStackTrace();}}public void run() {try {for (int i = 0; i < 10; i++) {out.println("cliend is :" + id + ":" + i);String str;try {str = in.readLine();System.out.println(str);} catch (IOException e) {e.printStackTrace();}}out.println("END");} finally {try {socket.close();} catch (IOException e) {threadcount--;}}}}

服务器监听,并创建新的

import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class MultiServer {static final int PORT = 8080;public static void main(String[] args) throws IOException {ServerSocket s = new ServerSocket(PORT);System.out.println("Server Started");try {while (true) {Socket socket = s.accept();try{// 每一个访问该端口的,都从新一个线程new ServerThread(socket);}catch (IOException e) {socket.close();} }} finally{s.close();}}}

模拟多个客户端

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;public class ClientThread extends Thread {private Socket socket;private BufferedReader in;private PrintWriter out;private static int counter = 0;private int id = counter++;private static int threadcount = 0;public static int getThreadCount() {return threadcount;}// 客户端的构造,需要地址public ClientThread(InetAddress addr) {System.out.println("client is :" + id);threadcount++;try {socket = new Socket(addr, 8080);} catch (IOException e) {e.printStackTrace();}try {in = new BufferedReader(new InputStreamReader(socket.getInputStream()));out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);start();} catch (IOException e) {try {socket.close();} catch (IOException e1) {e1.printStackTrace();}e.printStackTrace();}}public void run() {try {for (int i = 0; i < 10; i++) {out.println("cliend is :" + id + ":" + i);String str;try {str = in.readLine();System.out.println(str);} catch (IOException e) {e.printStackTrace();}}out.println("END");} finally {try {socket.close();} catch (IOException e) {threadcount--;}}}}

小结:从代码上看,其实很简单,以前假设 我是到你家,8080端口去买东西 ,聊天什么的。现在有很多人去你家,同一个端口做事。因此每一个人都创建一个单独的线程,隔离出来就行了。



分享给朋友:
您可能感兴趣的文章:
随机阅读: