杂谈socket编程
作者:xcbeyond
疯狂源自梦想,技术成就辉煌!微信公众号:《程序猿技术大咖》号主,专注后端开发多年,拥有丰富的研发经验,乐于技术输出、分享,现阶段从事微服务架构项目的研发工作,涉及架构设计、技术选型、业务研发等工作。对于Java、微服务、数据库、Docker有深入了解,并有大量的调优经验。
最近在写一些与网络编程相关的小工具,不得不再把网络编程的知识再回顾回顾了。一提起网络编程,势必局想到了一位核心人物Socket,是她撑起了网络编程的半边天,使得网络编程得以继续。
什么是Socket?
通常也称作"套接字",应用程序通过Socket向网络发出请求或者应答网络请求。它是在应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,用来组织传输的数据。下面就用一张图来说明下“三次握手”:
网络间的通信,是建立在授受双方的,即:服务器与客户端。服务器端时刻处于启动状态,不停地监听着客户端发来的请求信息,并给予应答,当客户端向服务器发来一条数据请求时,服务器接受到了这条请求后,验证成功后,给出回复,建立链接通信,即一次握手。类似数据传输交换、断开链接又是两次握手。下面就以一段代码来做一分析说明吧。(Java版)
服务端:
<span style="font-size:14px;">import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* FTP服务器端
* @author xcbeyond
* 2014-6-7 22:12:21
*/
public class FtpServer {
public static void main(String[] args) throws Exception{
FtpServer server = new FtpServer();
server.listen(8800);
}
//用来时刻监听来自客户端请求的监听者
public void listen(int port) throws Exception{
ServerSocket ss = new ServerSocket(port);
while(true) {
System.out.println("等待客户端连接...");
Socket socket = ss.accept();
System.out.println("客户连接进来了。");
new ClientAgent(socket).start();
}
}
class ClientAgent extends Thread{
Socket socket;
InputStream in;
OutputStream out;
public ClientAgent(Socket socket) throws Exception{
this.socket = socket;
in = socket.getInputStream();
out = socket.getOutputStream();
}
@Override
public void run() {
BufferedReader in = new BufferedReader(
new InputStreamReader(this.in));
PrintWriter out = new PrintWriter(this.out,true);//true自动清除缓存 相当于fulsh()
try{
out.println("text,1");
out.println("你好欢迎使用FTP Demo!");
while(true) {
String cmd = in.readLine();
if("?".equals(cmd)) {
out.println("text,1");
out.println("支持命令:ls,get,?,bye");
}
else if("ls".equals(cmd)) {
listDir(out);
}
else if(cmd.matches("^get\\s+.+")) {
sendFile(cmd,out,this.out);
}
else{
out.println("text,1");
out.println("不知可否!");
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
private void sendFile(String cmd, PrintWriter out,OutputStream os) throws IOException{
String name = cmd.split("\\s+")[1];
File file = new File(name);
if(!file.exists()){
out.println("text,1");
out.println("没有找到文件! "+name);
return;
}
out.println("file,"+file.length()+","+name);
InputStream in = new BufferedInputStream(
new FileInputStream(file));
int b;
while((b = in.read())!=-1){
os.write(b);
}
os.flush();
in.close();
}
/**
* 列出文件目录
* @param out
*/
private void listDir(PrintWriter out) {
File dir = new File(".");
File[] files = dir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isFile();
}
});
out.println("text,"+files.length+1);
out.println("在目录:"+dir+"中,有文件:"+files.length);
for (File file : files) {
out.println(file.getName());
}
}
}
}
</span>
客户端:
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
/**
*
* @author xcbeyond
* 2014-6-7 23:16:53
*/
public class FtpClient {
Socket socket;
OutputStream out;
InputStream in;
public static void main(String[] args) throws Exception{
FtpClient client = new FtpClient();
client.open("localhost",8800);
}
public void open(String host,int port) throws Exception{
socket = new Socket(host,port); //对指定IP,端口的服务程序发出请求,建立通信
in = socket.getInputStream();
out =socket.getOutputStream();
new RequestSender(out).start();
new ResponseReceiver(in).start();
}
class RequestSender extends Thread{
OutputStream out;
public RequestSender(OutputStream out) {
this.out = out;
}
@Override
public void run() {
PrintWriter out = new PrintWriter(this.out,true);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String str;
try{
while((str = in.readLine())!=null) {
out.println(str);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
class ResponseReceiver extends Thread {
InputStream in;
public ResponseReceiver(InputStream in) {
this.in = in;
}
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(this.in));
try{
String str;
while((str = in.readLine())!=null) {
if(str.startsWith("text")) {
String num = str.substring(str.indexOf(",")+1);
printText(in,Integer.parseInt(num));
}
else if(str.startsWith("file")){//file,4567,filename
saveFile(this.in,str);
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
/**
* 保存文件
* @param in
* @param size
*/
private void saveFile(InputStream in, String head) throws IOException{
String[] data = head.split(",");
int length = Integer.parseInt(data[1]);
String name = data[2];
OutputStream out = new BufferedOutputStream(new FileOutputStream("ftp-"+name));
for (int i = 0; i < length; i++) {
int b = in.read();
out.write(b);
}
out.close();
System.out.println("下载了文件:"+name);
}
/**
* 打印出文本内容
* @param in
* @param num
* @throws Exception
*/
private void printText(BufferedReader in, int num) throws Exception{
for (int i = 0; i < num; i++) {
System.out.println(in.readLine());
}
}
}
}