给出一个C++或Java编写的ftp服务器程序
Socket TCP
反射API介绍
4.Java Socket编程 TCP 协议编程
1) TCP工作模型: 先找
堂(主机/IP), 到食堂以后找窗口
(Socket/套接字 端口号), 服务员等待连接,客户向服务员发起连接
连接以后, 一个窗口可以为每个客户安排一个服务员(线程)提供服务,
每个服务过程可以双向交流通讯(流), 通讯完成后要关闭连接.
5. TCP 服务端编程(食堂)(java.io.*,java.net.*,java.lang.*)
1) 创建ServerSocket实例绑定一个服务端口(Socket/套接字 端口号)
2) 开始ServerSocket实例 的监听, 等待客户端的连接
3) 如果有客户连接进来, 就获得了客户的套接字(Socket)实例
客户的套接字(Socket)实例中包括与客户端建立的连接流
4) 为这个客户(Socket) 创建一个服务线程, 提供服务(run方法)
5) 继续等待下一个连接, 返回到2)
6) 服务线程 完成通讯服务过程
7) 端口号: 0~65535, 1K以下留给系统使用
6. TCP 客户端编程
1) 创建Socket 实例, 连接到服务器端, 成功创建s就表示连接到了
服务器
Socket s = new Socket(“host”, port)
2) 客户端 Socket 与服务器端 Socket 对应, 都包含输入, 输出流
客户端的s.getInputStream() 连接于服务器s.getOutputStream()
客户端的s.getOutputStream()连接于服务器s.getInputStream()
3) 使用线程处理 网络流
7. Java 反射
1) 反射是Java自我管理(类, 对象)的机制
2) * 可以通过反射机制发现对象的类型 发现类型的方法/属性/构造器
3) * Java 反射 可以创建对象 并 访问任意对象方法和属性等
4) Class 加载
类加载到内存: java 将磁盘类文件加载到内存中,为一个对象(实例)
这个对象是Class的实例, 也就是 这些对象都是Class实例
5)Class 实例代表Java中类型, 基本类型的类型: int.class, long.class
类类型 Class 实例获得如下:
Class cls = String.class;
Class cls = Class.forName(“java.lang.String”);
Class cls = “abc”.getClass();
以上方法获得cls 是同一个对象, 就是String 类内存加载的结果
package javase2.day06.ftp;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
/**
* ftp 客户端 可以使用命令 ls pwd get
*/
public class FtpClient {
public static void main(String[] args)
throws IOException{
FtpClient client = new FtpClient();
client.open();
}
public void open() throws IOException{
Socket s = new Socket(“www.easyaq.com”, 9000);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//处理客户端对服务器的请求
new RequestProcess(out).start();
//处理服务器的反馈信息
new ResponseProcess(in).start();
}
//处理客户端对服务器的请求
class RequestProcess extends Thread{
OutputStream out;
public RequestProcess(OutputStream out) {
this.out = out;
}
public void run() {
try{
Scanner sc = new Scanner(System.in);
while(true){
String s = sc.nextLine();
IOUtils.println(out, s);
if(s.equals(“bye”)){
System.exit(0);
}
}
}catch(IOException e){
e.printStackTrace();
}
}
}
class ResponseProcess extends Thread{
InputStream in;
public ResponseProcess(InputStream in) {
this.in = in;
}
public void run() {
try{
while(true){
String header = IOUtils.readLine(in);
if(header.startsWith(“text,”)){
show(header,in);
}else if(header.startsWith(“file,”)){
save(header, in);
}
}
}catch(IOException e){
e.printStackTrace();
}
}
}
public void show(String header, InputStream in)
throws IOException {
int n = Integer.parseInt(header.split(“,”)[1]);
for(int i=0; in; i++){
String s = IOUtils.readLine(in);
System.out.println(s);
}
}
public void save(String header, InputStream in)
throws IOException{
File dir = new File(“ftp”);
if(!dir.exists()){
dir.mkdir();
}
//header: file,10,filename
String[] data = header.split(“,”);
long length = Long.parseLong(data[1]);
String filename = data[2];
File file = new File(dir, filename);
BufferedOutputStream out =
new BufferedOutputStream(
new FileOutputStream(file));
for(long i=0; ilength; i++){
int b = in.read();
out.write(b);
}
out.close();
}
}
package javase2.day06.ftp;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 模拟FTP服务器, 支持命令pwd,ls,get file
*
* 协议: type,length,value TLV格式
*
* 文本: text,5\nline1\nline2\nline3\nline4\nline5\n
* 文件: file,4,filename\n 41 42 43 44
*
* text,5\nline1\nline2\nline3\nline4\nline5\nfile,4,filename\n 41 42 43 44
*/
public class FtpServer {
public static void main(String[] args)
throws IOException{
FtpServer server = new FtpServer();
server.start();
}
public void start() throws IOException{
ServerSocket ss = new ServerSocket(9000);
while(true){
Socket s = ss.accept();
new Agent(s).start();
}
}
class Agent extends Thread{
Socket s;
public Agent(Socket s) {
this.s = s;
}
public void run() {
try{
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//向客户端发送, 先发协议头,再发送文本行
out.write(“text,1\n”.getBytes());//协议头
//发送消息内容, 一行文本消息
out.write(“欢迎使用FTP演示服务器!\n”.getBytes());
out.flush();
while(true){
//读取客户端发送到命令
String cmd = IOUtils.readLine(in).trim();
if(“pwd”.equals(cmd)){//显示当前目录
pwd(out);
}else if(“ls”.equals(cmd)){
ls(out);
}else if(cmd.startsWith(“get “)){
get(cmd, out);
}else if(“bye”.equalsIgnoreCase(cmd)){
IOUtils.println(out, “text,1”);
IOUtils.println(out, “Bye, Bye!”);
s.close();
}else{
out.write(“text,1\n”.getBytes());//协议头
out.write(“只支持pwd,ls,get,bye!\n”.getBytes());
out.flush();
}
}
}catch(IOException e){
e.printStackTrace();
}
}
}
public void pwd(OutputStream out)
throws IOException{
File dir = new File(“.”);
IOUtils.println(out, “text,1”);
IOUtils.println(out, dir.getCanonicalPath());
}
public void ls(OutputStream out)
throws IOException{
File dir = new File(“.”);
File[] files = dir.listFiles();
IOUtils.println(out, “text,”+files.length);
for (File f : files) {
if(f.isDirectory()){
IOUtils.println(out, “[“+f.getName()+”]”);
}else{
IOUtils.println(out, f.getName());
}
}
}
public void get(String cmd, OutputStream out)
throws IOException{
//cmd=”get filename”
String name = cmd.split(“\\s+”)[1];
File file = new File(name);
if(! file.exists()){
IOUtils.println(out, “text,1”);
IOUtils.println(out, “没有文件呀!”+name);
return;
}
//文件协议头:
IOUtils.println(out,
“file,”+file.length()+”,”+name);
FileInputStream in =
new FileInputStream(file);
IOUtils.cp(in, out);
out.flush();
in.close();
IOUtils.println(out, “text,1”);
IOUtils.println(out, “发送成功:”+name);
}
}
(用C语言实现)客户端如何通过socket调用服务器函数
socket是用来和服务器通信的,无法直接调用服务器函数。
要实现功能,可以和服务器约定协议。
比如,在与服务器通信连接后,发送一系列标识符,最后加一个函数id,表示要求服务器调用约定的某一个函数。
服务器在接收到后,执行对应的函数,将结果返回给客户端即可。
linux服务器接收发送报文
它使用状态的“关联”(协会),两对SCTP用户协议之间的信息交换条款的定义。 SCTP也是一个面向连接的,但在概念上,SCTP“关联”更广泛的TCP连接相比,只有一个TCP连接的源地址和目的地址,SCTP提供了另一种方式为每个SCTP端点的运输提供了一组地址等端点传输地址= IP地址+端口号。
继承的TCP功能的基础上,SCTP提供了一些额外的功能:
1有序传输中的用户数据的多个“流”(流)
“流”是一系列的TCP中指的字节,而在SCTP是指某个系列的用户消息被发送到上层协议,这些消息的顺序与在流之内的其他消息。当建立关联,SCTP的用户的数据流的数目,可被提供给相关联的载体。此号码被商定的流的??数目与源端的用户相关联的消息。 SCTP为每个邮件中的链接发送给同行的流分配的序列号。在接收端,SCTP,以确保在一个给定的消息流的顺序被发送。另一方面,当工作流正在等待的下一个非顺序的用户消息的其他数据流的发送时,将继续下去。
2根据所发现的路径MTU(最大传输单元)的大小的用户数据切片
为了确保一致的SCTP报文发送到较低的路径MTU,SCTP用户消息分得一杯羹。传递给上部SCTP用户在接收端,切片重组。
3选择性确认(SACK)和拥塞控制
选择性确认数据包丢失,TCP序列号被返回给发送者已经成功地接收到的数据字节的序列号(不包括根据确认的字节数)的认可,并在SCTP反馈给发件人丢失,并要求序列号的消息重发。
SCTP使用的TCP拥塞控制技术,包括慢启动,拥塞避免和快速重传。因此,当一个共存和TCP应用程序时,SCTP的应用程序可以接收部分SCTP的网络资源。
4块(块)结合。
选择性地绑定到??SCTP包,即多个用户消息的消息发送到一个或多个数据结构的SCTP – “块”,SCTP储备应用程序消息传递框架边界。不同类型的块可以绑定到一个SCTP报文,但任何一个数据块之前,必须放在控制块。
5路径管理
SCTP路径管理功能主要是负责为目的地的运输提供了一个选择的目标地址的传输地址的远程地址,它是基于两个方面:SCTP用户的说明和合格的目的地。当其他流量控制不能提供可达性信息,定期扫描路径管理功能链接到SCTP报告在远程传输地址发生变化的可达性。 SCTP路径管理功能模块还负责建立链接,该报告的末端的本地地址,传输地址告诉SCTP用户的远程回报。
6,支持多归位
当SCTP传输的数据包的目的IP地址,如果IP地址是不可达的,SCTP消息重新路由到备用的IP地址。因此,在相关联,即使在两端的,可以容忍网络级别的错误的一端。
7对拒绝服务攻击(DoS)
DoS攻击的方法有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的资源,从而使合法用户无法得到服务的响应。 SYN洪水攻击是一种拒绝服务攻击实例,是最好的方式了黑客攻击。针对SYN Flooding攻击的目标主机上,SCTP关联的初始化阶段,实施以“Cookie”的安全机制。
8支持多种传输模式
严格有序转移(如TCP)的有序转移(如每流)和无序传输(如UDP)的一部分。
2 SCTP报文结构
SCTP分组结构的数据分组,第一部分可以遵循由可变长度的数据块中的一个或多个。块类型 – 长度 – 值(TLV)格式。源端口,目的端口,校验的意义是与TCP类似的意义。确认标签保存价值的交流,第一次在SCTP握手初始标签。如果任何SCTP报文不包括联想这样的标签,当到达的时间将是在接收端丢弃。
包含的块类型,标记的转让处理,在每个块中的块长度,TLV。不同的块类型,可用于发送控制信息或数据。
发送序列号(TSN)和流序列号(SSN)是两个不同的序列号,TSN,以确保可靠性整个关联的SSN保证整个流的有序性,因此,在发送的数据的可靠性订货区分开来。
3 SCTP数据传输
4.1 SCTP四次握手的原则,抵制SYN洪水攻击
SCTP关联定义为:主机A的IP地址] + [主机的端口] + [IP地址的主机B] + [B主机端口。因此,相应的组的每个端部中的IP地址的任何一个可以是标记相关的,通过四向握手,作为相应的源/目的地地址和结束SCTP主机交换通信状态。
SYN洪水利用所固有的脆弱性,TCP / IP,TCP三次握手面向连接的SYN洪水的存在基础。 SYN Flooding攻击原理是:大量的恶意攻击者向服务器发送一个SYN包,服务器发出一个SYN + ACK数据包无法收到客户端的ACK包(第三次握手无法完成),服务器端将保持一个非常大名单的半连接,消耗大量的CPU时间和内存资源,也能保持此列表中的IP SYN + ACK的重试。服务器端将忙于处理攻击者伪造的TCP连接请求以及没有时间忽略正常的客户请求,从正常的客户的角度来看,服务器失去了响应。
在SCTP四次握手的INIT消息,接收端不保存任何状态信息或分配的任何资源,这样你就可以防止DoS攻击,如SYN洪水。 INIT-ACK消息发送,使用了一种机制 – “状态曲奇”的cookie的发送者建立自己的国家所需的全部信息。
SCTP产生一个Cookie状态过程如下:
1。收到的INIT发出的INIT ACK数据块的信息来创建一个关联的TCB(传输控制块)。
在TCB中,生存在协议参数设置为“有效的Cookie时间,创建日期设置为当前日期。
3根据TCB收集重建的TCB所需的最小的子集的信息,这个子集和密钥来产生一个MAC(消息认证码)。
用最小的子集的信息和MAC产生状态Cookie。
5。在发送的INIT ACK(含状态cookie参数),发送者必须删除TCB,以及任何相关的新的关联的本地资源。
INIT和INIT ACK必须包含建立初始状态所需的参数:一组IP地址,以确保可靠的传输的初始TSN,每一个收到的SCTP包中必须包含初始标签,每一端的请求发出的数据流的数量并在每一端可以支持接收的数据流的数量。交换这些消息,INIT COOKIE-ECHO消息的发送者被送回的状态Cookie。接收端在接收COOKIE-ECHO饼干的状态,完成重建自己的国家和回送COOKIE-ACK确认该协会已成立。 COOKIE-ECHO和COOKIE-ACK的用户数据信息可以绑定到每个包。
因此,使用上述的以这样的方式,即使接收INIT消息,接收终端,也没有任何的资源消耗:它既不分配任何系统资源,并且不保存的新的关联的状态,它是只对口援建的状态状态的Cookie作为一个参数,它包含每一个回送的INIT-ACK消息,并最终状态cookie COOKIE-ECHO消息发送回。
2.2 SCTP的数据交换
正常的两个SCTP主机之间的数据交换。 SCTP主机发送SACK块,用来确认每一个收到的SCTP报文。 SACK的完全描述的接收侧的状态,可以使发送侧决定的重发,因此,在根据对SACK。 SCTP支持TCP快速重传和超时重传算法类似。
SCTP和TCP数据包丢失,使用不同的机制:TCP序列号空缺已被填补缺口,直到收到,发送丢失的数据包数据的序列号是高于之前。但是,SCTP即使收到订单的序列号空缺,并会不断发回数据。
3.3 SCTP关联关闭
面向连接的传输协议,SCTP还可以使用与TCP的三次握手关闭相关,但有一点不同:在“关联关闭”的过程中保持连接打开一个TCP终端,新的数据来自对等体,但不支持TCP SCTP这个“半封闭”状态。 1日发布由主机A“OFF”(关闭)块终止与主机B,主机A就会进入“SHUTDOWN-PENDING”状态,相应的动作是:不再接受上层应用的数据,并且只发送队列中剩余的数据,进入“SHUTDOWN-SENT”状态。
一旦主机B接收到“OFF”挡,进入“SHUTDOWN-RECEIVED”状态,与主机A,不再接受上层应用的数据,只发送队列中剩余的数据。
主机A再发送“关闭”块,剩余的数据已经达到主机B发出的通知,并重申,该协会正在关闭。
当第二个获得“关闭”块,主机B发送确认关闭“块。
随后的主机发送“关闭”结束“块完成关闭的关联。
4结论
SCTP是开发用于传输信令流量,但它有一定的优势,先进的TCP协议机制,如选择性确认,快速重传,无序提交,因此,它也满足高性能传输的需求,这将赋予它更广泛的应用的要求。目前,有各种各样的操作系统都支持SCTP,如Linux,AIX和Solaris上,Windows中,FressBSD。不同的协议之间的互操作性测试取得成功,揭示了SCTP正走向商业产品的道路。
IEFT致力于SCTP进一步的,以使其更好地满足下一代应用的需求,如支持IPv6地址,解决对端的IPv6站点本地和链路本地地址不连接的问题,以及在现有的关联动态添加或删除IP地址,而无需重新启动关联。
此外,在第三代移动通信,SCTP信令承载层的选择之一,它的应用及其性能评价是还待研究。
参考文献:
在java中怎么将一组数据从客户端发送到服务器端???
通过反射!
下面是一个服务器与客户端信息交互的例子:
反射API介绍
4.Java Socket编程 TCP 协议编程
1) TCP工作模型: 先找
堂(主机/IP), 到食堂以后找窗口
(Socket/套接字 端口号), 服务员等待连接,客户向服务员发起连接
连接以后, 一个窗口可以为每个客户安排一个服务员(线程)提供服务,
每个服务过程可以双向交流通讯(流), 通讯完成后要关闭连接.
5. TCP 服务端编程(食堂)(java.io.*,java.net.*,java.lang.*)
1) 创建ServerSocket实例绑定一个服务端口(Socket/套接字 端口号)
2) 开始ServerSocket实例 的监听, 等待客户端的连接
3) 如果有客户连接进来, 就获得了客户的套接字(Socket)实例
客户的套接字(Socket)实例中包括与客户端建立的连接流
4) 为这个客户(Socket) 创建一个服务线程, 提供服务(run方法)
5) 继续等待下一个连接, 返回到2)
6) 服务线程 完成通讯服务过程
7) 端口号: 0~65535, 1K以下留给系统使用
6. TCP 客户端编程
1) 创建Socket 实例, 连接到服务器端, 成功创建s就表示连接到了
服务器
Socket s = new Socket(“host”, port)
2) 客户端 Socket 与服务器端 Socket 对应, 都包含输入, 输出流
客户端的s.getInputStream() 连接于服务器s.getOutputStream()
客户端的s.getOutputStream()连接于服务器s.getInputStream()
3) 使用线程处理 网络流
7. Java 反射
1) 反射是Java自我管理(类, 对象)的机制
2) * 可以通过反射机制发现对象的类型 发现类型的方法/属性/构造器
3) * Java 反射 可以创建对象 并 访问任意对象方法和属性等
4) Class 加载
类加载到内存: java 将磁盘类文件加载到内存中,为一个对象(实例)
这个对象是Class的实例, 也就是 这些对象都是Class实例
5)Class 实例代表Java中类型, 基本类型的类型: int.class, long.class
类类型 Class 实例获得如下:
Class cls = String.class;
Class cls = Class.forName(“java.lang.String”);
Class cls = “abc”.getClass();
以上方法获得cls 是同一个对象, 就是String 类内存加载的结果
package javase2.day06.ftp;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Scanner;/** * ftp 客户端 可以使用命令 ls pwd get */public class FtpClient { public static void main(String[] args) throws IOException{ FtpClient client = new FtpClient(); client.open(); } public void open() throws IOException{ Socket s = new Socket(“www.easyaq.com”, 9000); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); //处理客户端对服务器的请求 new RequestProcess(out).start(); //处理服务器的反馈信息 new ResponseProcess(in).start(); }//处理客户端对服务器的请求 class RequestProcess extends Thread{ OutputStream out; public RequestProcess(OutputStream out) { this.out = out; } public void run() { try{ Scanner sc = new Scanner(System.in); while(true){ String s = sc.nextLine(); IOUtils.println(out, s); if(s.equals(“bye”)){ System.exit(0); } } }catch(IOException e){ e.printStackTrace(); } } } class ResponseProcess extends Thread{ InputStream in; public ResponseProcess(InputStream in) { this.in = in; } public void run() { try{ while(true){ String header = IOUtils.readLine(in); if(header.startsWith(“text,”)){ show(header,in); }else if(header.startsWith(“file,”)){ save(header, in); } } }catch(IOException e){ e.printStackTrace(); } } } public void show(String header, InputStream in) throws IOException { int n = Integer.parseInt(header.split(“,”)[1]); for(int i=0; in; i++){ String s = IOUtils.readLine(in); System.out.println(s); } } public void save(String header, InputStream in) throws IOException{ File dir = new File(“ftp”); if(!dir.exists()){ dir.mkdir(); } //header: file,10,filename String[] data = header.split(“,”); long length = Long.parseLong(data[1]); String filename = data[2]; File file = new File(dir, filename); BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(file)); for(long i=0; ilength; i++){ int b = in.read(); out.write(b); } out.close(); } }———————————–package javase2.day06.ftp;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** * 模拟FTP服务器, 支持命令pwd,ls,get file * * 协议: type,length,value TLV格式 * * 文本: text,5\nline1\nline2\nline3\nline4\nline5\n * 文件: file,4,filename\n 41 42 43 44 * * text,5\nline1\nline2\nline3\nline4\nline5\nfile,4,filename\n 41 42 43 44 */public class FtpServer { public static void main(String[] args) throws IOException{ FtpServer server = new FtpServer(); server.start(); } public void start() throws IOException{ ServerSocket ss = new ServerSocket(9000); while(true){ Socket s = ss.accept(); new Agent(s).start(); } } class Agent extends Thread{ Socket s; public Agent(Socket s) { this.s = s; } public void run() { try{ InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); //向客户端发送, 先发协议头,再发送文本行 out.write(“text,1\n”.getBytes());//协议头 //发送消息内容, 一行文本消息 out.write(“欢迎使用FTP演示服务器!\n”.getBytes()); out.flush(); while(true){ //读取客户端发送到命令 String cmd = IOUtils.readLine(in).trim(); if(“pwd”.equals(cmd)){//显示当前目录 pwd(out); }else if(“ls”.equals(cmd)){ ls(out); }else if(cmd.startsWith(“get “)){ get(cmd, out); }else if(“bye”.equalsIgnoreCase(cmd)){ IOUtils.println(out, “text,1”); IOUtils.println(out, “Bye, Bye!”); s.close(); }else{ out.write(“text,1\n”.getBytes());//协议头 out.write(“只支持pwd,ls,get,bye!\n”.getBytes()); out.flush(); } } }catch(IOException e){ e.printStackTrace(); } } } public void pwd(OutputStream out) throws IOException{ File dir = new File(“.”); IOUtils.println(out, “text,1”); IOUtils.println(out, dir.getCanonicalPath()); } public void ls(OutputStream out) throws IOException{ File dir = new File(“.”); File[] files = dir.listFiles(); IOUtils.println(out, “text,”+files.length); for (File f : files) { if(f.isDirectory()){ IOUtils.println(out, “[“+f.getName()+”]”); }else{ IOUtils.println(out, f.getName()); } } } public void get(String cmd, OutputStream out) throws IOException{ //cmd=”get filename” String name = cmd.split(“\\s+”)[1]; File file = new File(name); if(! file.exists()){ IOUtils.println(out, “text,1”); IOUtils.println(out, “没有文件呀!”+name); return; } //文件协议头: IOUtils.println(out, “file,”+file.length()+”,”+name); FileInputStream in = new FileInputStream(file); IOUtils.cp(in, out); out.flush(); in.close(); IOUtils.println(out, “text,1”); IOUtils.println(out, “发送成功:”+name); }}