socket 编程之简单应用


 socket 编程之简单应用

    上一篇小作中较详细的说明了socket编程的实现过程,在最后,我们已经可以在客户端发送一条字符串,就可在服务器端接收到了,恩,好象很有趣。可这是远远不够的。

    我们学习一项新技术,不是要具体的实现这项技术,而是要用这项技术来解决我们手头的问题。而鼎鼎大名的socket也不仅仅是发送一条字符串,然后在接收这条字符串。好,今个小弟就在这里班门弄斧了。

    既然socket技术可以让两个不同的进程间进行通信,而这两个进程可以处于不同的计算机上,只是需要有正确的物理连接,那好,现在的问题是:客户端程序能否在服务器端程序的帮助下获取一些服务端主机的信息呢?哦,好象有木马的味道啊!!!呵呵。这个问题听起来很有吸引力,但我们稍做思考,就觉得这个问题好象很幼稚,既然可互发消息,那服务器端程序把任何信息都可当作消息内容发送回客户端。

    那好,让socket解决以下两个问题:
1、取得服务器主机某个目录下的文件列表和目录列表,目录的路径需要客户端发送过来;
2、取得服务器主机某个文件的内容。

    以上几个问题很有代表性,如果成功,那服务器主机的整个文件系统就会展示给客户端。

    从这两个待解决的问题本身我们不难看出:
1、请求的服务类型是不同的,列目录或文件列表,或取得文件内容;
2、一种服务类型本身具有特定参数,如列目录列表需要父目录路径,取得文件内容需要有文件路径。

    哦,看来发送或接收的消息不象我们想的那么简单,我们需要对“消息”进行一下封装,以解决我们只能发送接收字符串的问题了,经过一些思考或称为设计,我把消息封装成如下结构:

// Message
// +- Protocol Version  1 byte
// +- Message type   2 bytes
// +- Message Length  2 bytes
// for ()
//  +- Patameter type  2 bytes
//  +- Patameter tag  1 byte
//  +- Patameter index  2 bytes
//  +- Patameter data length 2 bytes
//  +- Patameter data  var

简单的作一下说明
    Protocol Version 是为了以后的版本升级预留的,不同的值说明对消息的解释也不同;
    Message type 表示是什么类型的请求,列目录和取得文件内容两者的值是不同的;
    Message Length 表示参数的总长度;
    for () 表示可以有多个参数;
    Patameter type 表示参数类型,如是目录路径还是文件路径;
    Patameter tag 和 Patameter index,如果信息数据在一个Message中放不下。就会分几个Message去放,前者表示是否是最后一个Message,后者表示是第几个Message。如取得某个文件的内容,如果文件内容分两个Message存放,那第一个Message的Patameter tag为0,表示不是最后一个Message,Patameter index为0,表示是第一个Message,第二个Message的Patameter tag为1,表示是最后一个Message,Patameter index为1,表示是第二个Message,这将在客户端程序中进行解析;
    Patameter data length 表示Patameter data的长度;
    Patameter data 表示是参数的具体数据。

    以上的byte是unsigned char类型。不难算出,一个Message的长度最大为65535,够大了,我在代码中指定Message的最大长度为512,这到无所谓,值得一提的是,大多数Message的长度远没有达到这个长度,在发送消息时可不要都发出去,浪费了资源啊,要做到用多少占多少。这主要是在程序中去做了,在这里,只能这样说:不管Message的最大长度是多少,只发送它的有效数据就行了。

    对于新一代程序员来说,位移操作接触的不太多,基于以上数据结构要涉及到,我在这里作一个事例贴一些代码:

/**
 * Returns the type of this message object.
 */
int SockMsg::getMessageType(void) const {
    return (_data[1] << 8) | _data[2];
}

/**
 * Sets the type of this message object.
 */
void SockMsg::setMessageType(const int &type) {
    _data[1] = type >> 8;
    _data[2] = type;
}

以上是对消息类型的两个操作函数。

    恩,不错,我们构造一个Message对象,把原来发送的字符串用这个Message数据代替就行了。

在客户端,我们将以以下的方式发送Message了:

 申明一个SockMsg对象
 while(1) {
  获取用户操作

  if (列文件列表) {
   获取用户指定路径
   
   设置消息类型为——列文件
   设置消息参数
  }
  else if (获取文件内容) {
   获取用户指定文件名
   
   设置消息类型为——获取文件内容
   设置消息参数
  }
  else if (关闭连接) {
   break;
  }
  else {
   continue;
  }

  发送消息
  接受消息
 }
 closesocket();

在服务器端,要这样处理客户端发送来的消息:

 while (1) {
  if (接受消息成功) {
   if (获取消息类型为——关闭连接) {
    break;
   }
   else if (获取消息类型为——列文件) {
    获取参数值
    获取文件列表
    把文件列表以参数的形式加入到一个Message中
   }
   else if (获取消息类型为——取得文件内容) {
    获取参数值
    获取文件内容
    把文件内容以参数的形式加入到一个Message中,如果一个放不下,分若干个
   }
   发送消息
   
  }
 }

哦,好了,以上这是关键的逻辑处理。不过这已经是一个框架了,你可以在现有的基础上完善它,那可是有很多工作要做的啊。

我不太喜欢在文章中贴代码,写出逻辑处理显的很清晰,但在实际编程中会有很多问题需要处理,取得某个目录下的文件列表,或是读取一个文件的内容,不在本文的讨论范围,大家也各有个自的实现方法,都贴出来会很多,没有多大意义。我一直认为,编程序其实是体现一种思想,把自己的思想写出来就行了,别人觉得好就会加以采用。如果想看看我的源码,也在这个blog上。

好了,我就唠叨在这吧,关于socket技术的应用在这里只是冰山一角,只要你习惯于去思考,去实践,有不断的惊喜等着你,记住:天下事不过一琢磨!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值