Linux下C++ Socket编程

来源:互联网 发布:c语言如何生成exe文件 编辑:程序博客网 时间:2024/06/07 17:39
 8284人阅读 评论(5) 收藏 举报
socketlinuxc++server服务器exception

原文地址:http://tldp.org/LDP/LG/issue74/tougher.html

Linux Socket Programming In C++


内容提要

1. 简介

2. CS 通信概览

3. 简单的CS实现

3.1 Server - 建立监听Socket

3.2 Client - 连接到服务器

3.3 Server - 接受客户端连接测试

3.4 Client 和 Server - 发送和接收数据

编译和测试我们的CS

4.1 文件列表

4.2 编译和测试

5. 结论

1. 简介

Socket是进程之间交换数据的机制。这些进程即可以是同一台机器上的,也可以是通过网络连接起来的不同机器。一旦一个Socket连接建立,那么数据就能够双向传输,直到其中一端关闭连接。

由于我过去要在一个进行中的项目中使用Socket,所以我开发并提炼了几个C++类来封装原始Socket API调用。通常,请求数据的应用程序叫做客户端Client,而为请求服务叫做服务器Server。我创建了两个主要的类 ClientSocket 和 ServerSocket,用他们,客户端和服务器端就可以交换数据了。

本文的目标就是教会你如何再你的程序中使用 ClientSocket 和 ServerSocket。我们首先简要探讨一下cs通信,接着我们会编写一个简单且使用着两个类的server和client。

2. CS通信概览

再开始讨论具体代码之前,我们应该简要看一下一个典型的CS连接。如下这张表格给出了这些步骤的大概情况:

Server

Client

1. 建立一个监听端口,等待来自客户端的连接

2. 创建一个客户端端口,并且尝试链接到服务器。

3. 接受客户端的连接请求。

4. 发送和接受数据。

4. 发送和接受数据。

5. 关闭连接

5. 关闭连接

基本上说,首先,服务器监听一个端口,并且等待来自客户端的连接。之后客户端创建一个,并且尝试连接服务器。接着,服务器接受了来自客户端的连接,并且开始交换数据。一旦所有的数据都已经通过socket连接传输完毕,那么任意一方都可以关闭连接了。

3. 简单的CS实现

现在我们开始讨论一下代码了。那么在接下来的章节里面,我们回逐步建立CS双边代码来执行所有再前文中提到的功能。我们回实现一些典型的功能,例如创建服务器端口监听用的socket,接着创建客户端连接服务器的socket等等。所有这些代码可以在simple_server_main.cpp 和 simple_client_main.cpp 找到。

如果你仅仅想检验看看这些源码是否好用,那么请直接跳到这一节。它列出来项目中所用的所有的文件,并且讨论了如何编译和测试他们。

3.1 Server - 建立监听Socket

我们要坐的第一件事情就是要创建一个简单的服务器,用来监听来自客户端的请求。如下是用来建立一个服务器socket的代码:

列表1 : 创建 server socket ( 部分 simple_server_main.cpp 的代码)

#include "ServerSocket.h"
#include "SocketException.h"
#include <string>

int main ( int argc, int argv[] )
{
try
    {
      // 创建 server socket
      ServerSocket server ( 30000 );


      // 其余的代码是接受连接,处理请求等等
    }
catch ( SocketException& e )
   {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

return 0;
}

这就是创建一个server socket所需的一切了。ServerSocket 类的构造函数调用了一个必须的socket API来设置监听socket。它隐藏了很多细节,所以对你来说,所有要做的就是创建一个类的实例开始监听本地端口。

注意 try/catch 语句块。ServerSocket 和 ClientSocket 类使用了C++的异常处理。如果一个类方法因为某些原因调用失败,那么它就抛出SocketException 类型的异常,这个异常被定义再SocketException.h中。如果不处理这个异常,就是直接导致程序结束,所以最好处理一下。你可以通过调用SocketException 的 description() 方法来获取错误信息。


3.2 Client – 链接到服务器

CS连接的第二部是客户端的责任的,要尝试去连接server。代码跟刚才服务器的那个有些类似:

列表 2 : 创建一个client socket (simple_client_main.cpp 部分代码)

#include "ClientSocket.h"
#include "SocketException.h"
#include <iostream>
#include <string>

int main ( int argc, int argv[] )
{
try
    {
      // 创建一个 client socket
      ClientSocket client_socket ( "localhost", 30000 );


      // 其余的代码是发送请求,解析相应等等。
    }
catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\n";
    }

return 0;
}

通过创建一个 ClientSocket 类的实例, 你创建了一个linux的socket,并把它链接到主机的port上。类似于 ServerSocket 类,如果构造函数因为某些原因出现异常,那么就要抛出异常。

3.3 Server – 接受客户端连接

下一步的CS连接活动再server端。Server有责任接受来自client的连接请求,并且再两个socket之间打开通信的通道。

我们把这个功能添加到这个简单的server中,就是如下升级的版本:

列表 3 : 接受客户端连接 ( 部分 simple_server_main.cpp )

#include "ServerSocket.h"
#include "SocketException.h"
#include <string>

int main ( int argc, int argv[] )
{
try
    {
      // 创建socket
      ServerSocket server ( 30000 );

      while ( true )
       {
       ServerSocket new_sock;
       server.accept ( new_sock );


        // 其余代码,读取请求,发送回复等等。
        }
    }
catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

return 0;
}

接受一个连接请求,就是简单调用accept 方法。这个方法接受client的连接请求,并且给new_sock 赋予有关连接的信息。下一节我们回看到new_sock 是如何工作的。


3.4 Client 和 Server – 发送和接受数据

建立起连接之后,就开始发送和接受数据。

C++的高级特性之一就是运算符重载,或者简单的说,就是让某个运算符执行特定的功能。在ClientSocket 和 ServerSocket 类中,我重载了 << 和 >> 运算符,所以当使用的时候,他们就从socket里面写入或者读出数据。这里,是进一步更新过的server版本:

列表 4 : 简单server的实现 ( simple_server_main.cpp )

#include "ServerSocket.h"
#include "SocketException.h"
#include <string>

int main ( int argc, int argv[] )
{
try
    {
      // Create the socket
      ServerSocket server ( 30000 );

      while ( true )
        {

        ServerSocket new_sock;
        server.accept ( new_sock );

       try
           {
             while ( true )
              {
              std::string data;
              new_sock >> data;
              new_sock << data;
              }
           }
       catch ( SocketException& ) {}

        }
    }
catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

return 0;
}

new_sock 变量包含所有socket的信息,所以我们可以使用它来于客户端交换数据。"new_sock >> data;" 一行应该被解读为 "从 new_sock读数据,并且把他们放到我们的变量'data'中"。类似的,下一行就是把'data'中的数据通过连接发送回client。

如果你注意,你会发现我们已经创建了一个可以相应的服务器,但是没有任何数据从客户端发送过来。这里我们就来写一个client,它向server发数据,并且打印出server的响应。

列表 5 : 简单客户端的实现 ( simple_client_main.cpp )

#include "ClientSocket.h"
#include "SocketException.h"
#include <iostream>
#include <string>

int main ( int argc, int argv[] )
{
try
    {

      ClientSocket client_socket ( "localhost", 30000 );

      std::string reply;
      try
       {
       client_socket << "Test message.";
       client_socket >> reply;
       }
      catch ( SocketException& e) {}

      std::cout << "We received this response from the server:\n\"" << reply << "\"\n";;

    }
catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\n";
    }

return 0;
}

我们发送字符串是"Test Message." 到服务器,然后从服务器那里读取响应,并且通过标准输出输出。

4. 编译和测试我们的cs

现在我们要看一遍ClientSocket 和 ServerSocket 的基本使用方法,我们可以建立一个项目来测试一下。

4.1 文件列表

如下文件是我们的例子:

多方面的:

Makefile – 项目的makefile文件

Socket.hSocket.cpp – Socket类,实现的原生的socket API调用。

SocketException.h - SocketException 类

Server:

simple_server_main.cpp – 主文件

ServerSocket.hServerSocket.cpp - ServerSocket 类

Client:

simple_client_main.cpp – 主文件

ClientSocket.hClientSocket.cpp - ClientSocket

4.2 编译和测试

编译简单。首先吧所有的项目文件保存到一个目录下,之后再你的命令提示符下键入:

prompt$ cd directory_you_just_created
prompt$ make

这样就编译了所有的文件,并且创建了simple_server 和 simple_client 输出文件。要测试着两个输入文件,运行如下命令:

first prompt:
prompt$ ./simple_server
running....


second prompt:
prompt$ ./simple_client
We received this response from the server:
"Test message."

prompt$

之后客户端回发送文件到服务器,读取并且相应,之后把相应输出到标准输出上去。你可以运行任意多次客户端,服务器会相应每个请求。

5. 总结

Socket是进程间交换数据的简单且高校的途径。再这个文章里面,我们已经实现了socket通行,并且编写了一个简单的CS例子。现在你应该能在你的程序里面添加socket通信了,恭喜你!

Rob Tougher

Rob 是一位再纽约市中心区域工作的C++软件工程师。当不能在他最喜爱的平台上工作的时候,你能发现Rob正在沙滩上散步,和他的女友Nicole和他们的宠物狗Halley在一起。

CSDN下载源码:http://download.csdn.net/detail/engrossment/4470879

本文转自百度空间:http://hi.baidu.com/shywyz/blog/item/ffc55890ad1e2f84a977a48f.html

0 1
原创粉丝点击