C++ Socket编程实例解析

来源:互联网 发布:护肤方法 知乎 编辑:程序博客网 时间:2024/06/07 17:25

Socket

socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。—— [ 维基百科]

有三种不同形式的套接字:

  • 流式套接字(SOCK_STREAM)
    • 流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Transmission Control Protocol)协议。
  • 数据包套接字(SOCK_DGRAM)
    • 数据包套接字提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据包套接字使用UDP(User Datagram Protocol)协议进行数据的传输。由于数据包套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
  • 原始套接字(SOCK_RAW)
    原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW

基于TCP的Socket使用流式套接字,相比于使用数据包套接字的UDP来讲,TCP可以使程序员不必关心数据正确性及顺序正确性,缺点是效率较低。
基于TCP的Socket编程最常见的应用场景是在C/S架构下的分布式应用,针对客户端和服务器端提供不同的Socket系统调用。


下面举例说明其使用方式:

Server端

#include <Winsock2.h>#include <cstdio>#pragma comment(lib,"ws2_32.lib")void main(){    WSADATA wsaData;    SOCKET sockServer;    SOCKADDR_IN addrServer;    SOCKET sockClient;    SOCKADDR_IN addrClient;    WSAStartup(MAKEWORD(2,2),&wsaData);    sockServer=socket(AF_INET,SOCK_STREAM,0);    addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//INADDR_ANY表示任何IP    addrServer.sin_family=AF_INET;    addrServer.sin_port=htons(6000);//绑定端口6000    bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));    //Listen监听端    listen(sockServer,5);//5为等待连接数目    printf("服务器已启动:\n监听中...\n");    int len=sizeof(SOCKADDR);    charsendBuf[100];//发送至客户端的字符串    charrecvBuf[100];//接受客户端返回的字符串    //会阻塞进程,直到有客户端连接上来为止    sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);    //接收并打印客户端数据    recv(sockClient,recvBuf,100,0);    printf("%s\n",recvBuf);    //关闭socket    closesocket(sockClient);    WSACleanup();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

Client端

#include <Winsock2.h>#include <cstdio>#pragma comment(lib,"ws2_32.lib")void main(){    WSADATA wsaData;    SOCKET sockClient;//客户端Socket    SOCKADDR_IN addrServer;//服务端地址    WSAStartup(MAKEWORD(2,2),&wsaData);    //新建客户端socket    sockClient=socket(AF_INET,SOCK_STREAM,0);    //定义要连接的服务端地址    addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//目标IP(127.0.0.1是回送地址)    addrServer.sin_family=AF_INET;    addrServer.sin_port=htons(6000);//连接端口6000    //连接到服务端    connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));    //发送数据    char message[20]="HelloSocket!";    send(sockClient,message,strlen(message)+1,0);    //关闭socket    closesocket(sockClient);    WSACleanup();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

附Socket编程步骤:
服务器端编程的步骤:

1:加载套接字库,创建套接字(WSAStartup()/socket());

2:绑定套接字到一个IP地址和一个端口上(bind());

3:将套接字设置为监听模式等待连接请求(listen());

4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());

5:用返回的套接字和客户端进行通信(send()/recv());

6:返回,等待另一连接请求;

7:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

客户端编程的步骤:

1:加载套接字库,创建套接字(WSAStartup()/socket());

2:向服务器发出连接请求(connect());

3:和服务器端进行通信(send()/recv());

4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

转载于:http://blog.csdn.net/u012391923/article/details/52881938

原创粉丝点击