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.1
		InetAddress 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;

	// 服务器端的构造器,需要套接字socket
	public 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端口去买东西 ,聊天什么的。现在有很多人去你家,同一个端口做事。因此每一个人都创建一个单独的线程,隔离出来就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值