IOS TCP 小例子总结

@interface LocalFileTableViewController ()页面  的相关操作;




//    NSLog(@"%@",NSHomeDirectory());  沙箱,存放文件的地方,输出以后 在finder中 按住shift commond+G 进入文件夹,然后看刚才的数据参数进去没有




文件管理 
self.filePaths   = [NSMutableArray array];
    NSString *path  = @"/Users/gj/Desktop/day35";
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *fileNames = [fm contentsOfDirectoryAtPath:path error:nil];
    for (NSString *fileName in fileNames) {
        NSString *filePath = [path stringByAppendingString:fileName];
        
        [self.filePaths addObject:filePath];
    }




//页面的显示LocalFileTableViewController  显示界面;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    NSString *filePath = self.filePaths[indexPath.row];
    
    cell.textLabel.text = [filePath lastPathComponent];
    判断一个文件是否是文件夹的判断方法
    BOOL isDir;
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) {
如果是文件夹,则在右边设置角标
         [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
        cell.detailTextLabel.text = @"";
    }else{ 
        //如果是文件显示文件的大小
//        如果通过nsdata获取文件长度  需要把文件的数据先加载到内存中 才能获取长度
//        NSData *data = [NSData dataWithContentsOfFile:filePath];
//       fileHandle 处理文件内部数据 可以指定处理某个位置的数据
处理细节数据
        NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
        //设置游标到某个位置
//        [fileHandle seekToFileOffset:100];
       从游标的位置 读取某个长度的数据
//        NSData *data = [fileHandle readDataOfLength:200];
//        把游标设置到最后 并且得到文件长度
      long long fileLength = [fileHandle seekToEndOfFile];
        
        NSString *size = fileLength>1024?[NSString stringWithFormat:@"%lldKB",fileLength/1024] : [NSString stringWithFormat:@"%lldB",fileLength];
        
        cell.detailTextLabel.text = size;
        
    }
    return cell;
}








-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *filePath = self.filePaths[indexPath.row];
    BOOL isDir;
    if ([[NSFileManager defaultManager]fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) {
        LocalFileTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"LocalFileTableViewController"];
        vc.path = filePath;
        [self.navigationController pushViewController:vc animated:YES];
        
    }else{//如果是文件夹 就创建页面继续展开,  如果是文件就上传。。。
        //拿到文件的数据;
        NSData *fileData = [NSData dataWithContentsOfFile:filePath];
        
        self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self];
        
        //给谁发;
        [self.clientSocket connectToHost:@"192.168.1.56" onPort:8800 error:nil];
        
        [self.clientSocket writeData:fileData withTimeout:-1 tag:0];
        //做到这里  仍然发布过去。因为缺少文件的头,和文件的长度,
        
        NSString *headerString = [NSString stringWithFormat:@"upload&&%@&&%d",[filePath lastPathComponent],fileData.length];
    }    到这一步,拿到了数据的字符串;
到这一步虽然将要传的文件弄出来了,但是很多地方都会用到 ,所以需要声明一个工具类,用来方便的实现这些功能
}
上一步的下一步代码




-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *filePath = self.filePaths[indexPath.row];
    BOOL isDir;
    if ([[NSFileManager defaultManager]fileExistsAtPath:filePath isDirectory:&isDir]&&isDir) {
        LocalFileTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"LocalFileTableViewController"];
        vc.path = filePath;
        [self.navigationController pushViewController:vc animated:YES];
        
    }else{
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"确定上传是吧,别后悔,大家伙都能看见" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        [alertView show];
    }


}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 1) {
        //如果是文件夹 就创建页面继续展开,  如果是文件就上传。。。
        //拿到文件的数据;
        NSData *fileData = [NSData dataWithContentsOfFile:self.filePath];
        
        self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self];
        
        //给谁发;
        [self.clientSocket connectToHost:@"192.168.1.56" onPort:8800 error:nil];
        
        //做到这里  仍然发布过去。因为缺少文件的头,和文件的长度,
        
        NSString *headerString = [NSString stringWithFormat:@"upload&&%@&&%d",[self.filePath lastPathComponent],fileData.length];
        NSMutableData *allData = [Utils  getAllDataWithHeaderString:headerString];
        
        [allData appendData:fileData];
        
        [self.clientSocket writeData:allData withTimeout:-1 tag:0];
    }








3.工具类中 的实现代码Utils
这个Utils的工具类里面的作用是将文件的数据集合出来 然后实现一个方法 最终方便取
#import "Utils.h"


@implementation Utils
+(NSMutableData *)getAllDataWithHeaderString:(NSString *)headerString{
//将headerString的字符串转换成 二进制数据;
// 设置一个alldata集  存放数据,  数据的长度是100;
//   然后将数据集中的数据换成 二进制数据;    
    NSData *headerData = [headerString dataUsingEncoding:NSUTF8StringEncoding];
    
    NSMutableData *allData = [NSMutableData dataWithLength:100];
    
    [allData replaceBytesInRange:NSMakeRange(0, headerData.length) withBytes:headerData.bytes];
    
    return allData;
    
}
@end


#import "SeversViewController.h"
#import "AsyncSocket.h"
@interface SeversViewController ()<AsyncSocketDelegate>
@property (weak, nonatomic) IBOutlet UILabel *statusLable;
@property (weak, nonatomic) IBOutlet UIProgressView *myPV;
@property (nonatomic,strong)AsyncSocket *serverSocket;
@property (nonatomic,strong)AsyncSocket *myNewSocket;


@property (nonatomic,copy)NSString *host;


@property (nonatomic,strong)NSMutableData *allData ;


@property (nonatomic,copy)NSString *fileName;
@property (nonatomic)int fileLength;
@end


@implementation SeversViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    self.serverSocket = [[AsyncSocket alloc]initWithDelegate:self]; //初始化服务器;
    [self.serverSocket acceptOnPort:8800 error:nil];//监听端口号;
}


//正常的情况下,应该是服务器有一端,客户端一端, 这里这段代码是为了方便自己测试,服务器与客户端的状态;;;;;; 正常情况应该是点击服务器然后返回的时候服务器这个页面被干掉;  这里保留是为了方便测试
//
//-(void)viewDidDisappear:(BOOL)animated{
//    self.serverSocket.delegate = nil;
//}
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{
    //持有住连接进来的SOCKET   不能声明成NET开头的名字,会出错;
    self.myNewSocket = newSocket;
    
    
}
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
    // 链接上了就要不停的读客服端传过来的, 或者要传过来的数据;
    self.host = host;//在连接成功的时候把对方的IP地址记录一下;
    [self.myNewSocket readDataWithTimeout:-1 tag:0];
}
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    
    NSLog(@"%d",data.length);
    NSData *headData = [data subdataWithRange:NSMakeRange(0, 100)];
    
    NSString *headString = [[NSString alloc]initWithData:headData encoding:NSUTF8StringEncoding];
    
    
    if (headString&&[headString componentsSeparatedByString:@"&&"].count==3) {
        NSArray *headers =[headString componentsSeparatedByString:@"&&"];
        
        NSString *type = headers[0];
        if ([type isEqualToString:@"upload"]) {
            self.fileName = headers[1];
            self.fileLength = [headers[2]intValue];
            
            self.statusLable.text = [NSString stringWithFormat:@"%@真正在上传%@",self.host,self.fileName];
            
            
            //把剩余文件的数据取出来,放到可变data里
            NSData *subFileData = [data subdataWithRange:NSMakeRange(100, data.length-100)];
            
            self.allData = [NSMutableData data];
            
            [self.allData appendData:subFileData];
            
            //每次向服务器放数据的时候 都要将进度条的值改变。
            self.myPV.progress = self.allData.length *1.0/self.fileLength;
            
            if (self.allData.length == self.fileLength) {//这么判断表示已经传完了
                NSString *toPath = [NSString stringWithFormat:@"/Documents/%@",self.fileName];
                [self.allData writeToFile:toPath atomically:YES];
                
                //在传完的时候 告诉lable,谁谁谁 上传  什么文件完成
                self.statusLable.text = [NSString stringWithFormat:@"%@上传%@完成",self.host,self.fileName];


            }
            
            
            
            
            
            
        }
        
        
        
        else if([type isEqualToString:@"getFileList"]){
            
        }
        
        
        
        else//下载
        {
            
        }
    }else{//接收到的文件数据
        [self.allData appendData:data];
        
        //每次向服务器放数据的时候 都要将进度条的值改变。
        self.myPV.progress = self.allData.length *1.0/self.fileLength;
        
        if (self.allData.length == self.fileLength) {//这么判断表示已经传完了
            NSString *toPath = [NSString stringWithFormat:@"//Users/gj/Desktop/保存文件/%@",self.fileName];
            [self.allData writeToFile:toPath atomically:YES];
            
            self.statusLable.text = [NSString stringWithFormat:@"%@上传%@完成!!!",self.host,self.fileName];
        }
        
    }
    
    
    
    
    [sock readDataWithTimeout:-1 tag:0];
}






- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


/*
 #pragma mark - Navigation
 
 // In a storyboard-based application, you will often want to do a little preparation before navigation
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
 // Get the new view controller using [segue destinationViewController].
 // Pass the selected object to the new view controller.
 }
 */


@end




以上上传功能实现了,现在就剩余下载功能了;   实现服务器的文件列表了;
下载功能的代码实现:    
需要获取,文件夹下面的数据, 然后客户端才可以下载。 
实现这些东西,需要一个文件类, 客户端不断的接受数据  。

把对象转换成data类型  需要的代码与实现方法:
NSData *fileData  = [NSKeyedArchiver archivedDataWithRootObject:files];

@interface File : NSObject<NSCoding>
@property (nonatomic,copy)NSString *name;
@property (nonatomic)int length;

- (void)encodeWithCoder:(NSCoder *)aCoder{
   [aCoder encodeObject:self.name forKey:@"name"];
   [aCoder encodeInt:self.length forKey:@"length"];
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
   self = [super init];
   if (self) {
       self.name  = [aDecoder decodeObjectForKey:@"name"];
       self.length = [aDecoder decodeIntForKey:@"length"];
   }
   return self;

}



#import "ServerFilesTableViewController.h"

#import "AsyncSocket.h"

#import "Utils.h"

#import "File.h"

@interface ServerFilesTableViewController ()<AsyncSocketDelegate>

@property (nonatomic,strong)AsyncSocket *clientSocket;

@property (nonatomic,strong)NSArray *files;

 

@end

 

@implementationServerFilesTableViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.clientSocket = [[AsyncSocket alloc]initWithDelegate:self];

    [self.clientSocket connectToHost:@"192.168.1.12" onPort:8800 error:nil];

    

   NSString *headerString = @"getFileList&&&&";

   NSMutableData *data = [Utils getAllDataWithHeaderString:headerString];

    

    [self.clientSocket writeData:data withTimeout:-1 tag:0];

    [self.clientSocket readDataWithTimeout:-1 tag:0];

}

 

-(void)onSocket:(AsyncSocket *)sockdidReadData:(NSData *)data withTag:(long)tag{

//   //得到了服务器列表返回的数据

    self.files = [NSKeyedUnarchiver unarchiveObjectWithData:data];

    [self.tableView reloadData];//反归档将数据解出来;

    

    //因为这个数据不是立即就得到的 对页面的数据源进行了修改,(只要不是进到界面立即处理的)

    //只要是传过来的数据 有时差,就证明修改了数据源,就需要进行[self.tableView reloadData];

   // [self.tableView reloadData];

    

}

- (void)didReceiveMemoryWarning{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

 

 

 

 

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {

 

    // Return the number of rows in the section.

    return self.files.count;

}

 

 

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    

   File *file = self.files[indexPath.row];

   cell.textLabel.text = file.name;

   cell.detailTextLabel.text = [NSString stringWithFormat:@"%dB",file.length];

    

   return cell;

}

 

 

 

@end


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值