原文链接:http://www.cnblogs.com/lidabo/archive/2012/07/19/2598734.html

1.基于 TCP 的 socket 编程

/*
服务器端程序流程:
1.加载套接字库       WSAStartup
2.创建套接字           socket
3.将我们创建的套接字,绑定到本机地址的某一端口上     bind
4.为套接字设置监听模式,准备客户请求                          listen
5.等待客户请求到来。当请求到来,将接受连接请求,并返回一个新的对应于此次连接的套接字     accept
6.用新返回的套接字和客户端进行通信                             send / recv
7.在通信结束后,关闭套接字                                            closesocket客户端程序流程:
1.加载套接字库                           WSAStartup
2.创建套接字                              socket
3.向服务器发出请求连接            connect
4.和服务器进行通信                   send / recv
5.在通信结束后,关闭套接字    closesocket
*/

服务器端代码:

#include <Winsock2.h>
#include <stdio.h>   #pragma comment(lib, "Ws2_32.lib")   void main()
{  // 加载套接字库,并进行套接字的版本协商   WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   WSADATA     wsaData;            // 用于存储加载的 winsock 库版本信息   int         result;             // 用于检测 WSAStartup 函数运行结果
  wVersionRequested   = MAKEWORD(1, 1);   // 设定版本
  result = WSAStartup(wVersionRequested, &wsaData);  // 函数 WSAStartup 调用成功返回 0   // 出错处理   if (result != 0)                  {  return;  }  if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  {  WSACleanup();  return;  }  // 创建套接字   SOCKET      sock    = socket(AF_INET, SOCK_STREAM, 0);  // 绑定套接字   SOCKADDR_IN addrInfo;           // 存储本地主机地址信息
  addrInfo.sin_addr.S_un.S_addr   = htonl(INADDR_ANY);    // 本地主机地址   addrInfo.sin_port               = htons(6000);          // 端口号   addrInfo.sin_family             = AF_INET;              // 地址族
  bind(sock, (SOCKADDR *)&addrInfo, sizeof(SOCKADDR));  // 设置套接字监听模式   listen(sock, 5);  SOCKADDR_IN     addrInfoClient; // 存储客户端地址信息   int             len = sizeof(SOCKADDR);  while (true)  {  // 等待客户请求到来,并返回用于通信的套接字   SOCKET  sockConnect = accept(sock, (SOCKADDR *)&addrInfoClient, &len);  // 下面通过刚建立的套接字,来进行通信   // 发送数据   char    sendBuf[100];  sprintf(sendBuf, "这是服务器端,主机地址:%s", inet_ntoa(addrInfo.sin_addr));  send(sockConnect, sendBuf, strlen(sendBuf), 0);  // 接收数据   char    recvBuf[100];  recv(sockConnect, recvBuf, strlen(recvBuf), 0);  // 打印接收的数据   printf("%s\n", recvBuf);  closesocket(sockConnect);  }  }

客户端代码:

#include <Winsock2.h>
#include <stdio.h>   #pragma comment(lib,"Ws2_32.lib")   void main()
{  // 加载套接字库,并进行套接字的版本协商   WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   WSADATA     wsaData;            // 用于存储加载的 winsock 库版本信息   int         result;             // 用于检测 WSAStartup 函数运行结果
  wVersionRequested   = MAKEWORD(1, 1);   // 设定版本
  result = WSAStartup(wVersionRequested, &wsaData);  // 函数 WSAStartup 调用成功返回 0   // 出错处理   if (result != 0)                  {  return;  }  if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  {  WSACleanup();  return;  }  // 创建套接字   SOCKET      sockConnect = socket(AF_INET, SOCK_STREAM, 0);  // 向服务器发出连接请求   SOCKADDR_IN     addrInfoServer;     // 存储服务器端地址信息   addrInfoServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  addrInfoServer.sin_port             = htons(6000);  addrInfoServer.sin_family           = AF_INET;  // 向服务器发出连接请求   connect(sockConnect, (SOCKADDR *)&addrInfoServer, sizeof(SOCKADDR));  // 接收数据   char    recvBuf[100];  recv(sockConnect, recvBuf, sizeof(recvBuf), 0);  printf("%s\n", recvBuf);  // 发送数据   char    sendBuf[100] = "这是客户端\n";  send(sockConnect, sendBuf, sizeof(sendBuf) + 1, 0);  //关闭套接字
    closesocket(sockConnect);  WSACleanup();  system("pause");  return;
}

2. 基于 UDP 无连接的 socket 编程

/*服务端程序流程:
1.加载套接字库       WSAStartup
2.创建套接字           socket
3.将创建的套接字绑定到一个本地地址和端口上     bind
4.等待接收数据。后与客户端实现实时交流            recvfrom / sendto
5.关闭套接字          closesocket客户端程序流程:
1.加载套接字库     WSAStartup
2.创建套接字         socket
3.向服务器发送数据.后与服务端实现实时交流     recvfrom / sendto
4.关闭套接字        closesocket*/

服务器端代码:

#include <Winsock2.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")   void main()
{  // 加载套接字库,并进行套接字的版本协商   WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   WSADATA     wsaData;            // 用于存储加载的 wdnsock 库版本信息   int         result;             // 用于检测 WSAStartup 函数运行结果
  wVersionRequested = MAKEWORD(1, 1);     // 设定版本
  result  = WSAStartup(wVersionRequested, &wsaData);  // 函数 WSAStartup 调用成功返回 0   // 出错处理   if (result != 0)  {  return;  }  if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  {  WSACleanup();  return;  }  // 创建用于套接字   SOCKET  sockConnect = socket(AF_INET, SOCK_DGRAM, 0);  // 绑定套接字   SOCKADDR_IN     addrInfo;       // 存储本地主机地址信息
  addrInfo.sin_addr.S_un.S_addr   = htonl(INADDR_ANY);    // 本地主机地址     addrInfo.sin_port               = htons(6000);          // 端口号     addrInfo.sin_family             = AF_INET;              // 地址族
    bind(sockConnect, (SOCKADDR *)&addrInfo, sizeof(SOCKADDR));    // 等待接收数据   char    recvBuf[100];   // 接收数据缓冲   char    sendBuf[100];   // 发送数据缓冲   char    tempBuf[200];     SOCKADDR_IN     addrInfoClient; // 存储客户端地址信息   int             len = sizeof(SOCKADDR);  while (true)  {  recvfrom(sockConnect, recvBuf, strlen(recvBuf), 0, (SOCKADDR *)&addrInfoClient, &len);  if ('q' == recvBuf[0])  {  sendto(sockConnect, "q", strlen("q") + 1, 0, (SOCKADDR *)&addrInfoClient, len);  printf("聊天结束");  break;  }  sprintf(tempBuf, "%s 说:%s", inet_ntoa(addrInfoClient.sin_addr), recvBuf);  printf("%s\n", tempBuf);  // 发送数据   printf("我说:");  gets(sendBuf);  sendto(sockConnect, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrInfoClient, len);  }  // 关闭套接字
    closesocket(sockConnect);  WSACleanup();  }

客户端代码:

#include <Winsock2.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")   void main()
{  // 加载套接字库,并进行套接字的版本协商   WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   WSADATA     wsaData;            // 用于存储加载的 wdnsock 库版本信息   int         result;             // 用于检测 WSAStartup 函数运行结果
  wVersionRequested = MAKEWORD(1, 1);     // 设定版本
  result  = WSAStartup(wVersionRequested, &wsaData);  // 函数 WSAStartup 调用成功返回 0   // 出错处理   if (result != 0)  {  return;  }  if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  {  WSACleanup();  return;  }  // 创建套接字   SOCKET  sockConnect = socket(AF_INET, SOCK_DGRAM, 0);  // 向服务器发送数据   SOCKADDR_IN     addrInfoServer;     // 存储服务器地址信息
  addrInfoServer.sin_addr.S_un.S_addr   = inet_addr("127.0.0.1");     // 指定服务器地址   addrInfoServer.sin_port               = htons(6000);                // 端口号     addrInfoServer.sin_family             = AF_INET;                    // 地址族    int     len = sizeof(SOCKADDR);  char    recvBuf[100];   // 接收数据缓冲   char    sendBuf[100];   // 发送数据缓冲   char    tempBuf[200];     while (true)  {  // 发送数据   printf("我说:");  gets(sendBuf);  sendto(sockConnect, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrInfoServer, len);  // 等待并接收数据   recvfrom(sockConnect,recvBuf, strlen(recvBuf), 0, (SOCKADDR*)&addrInfoServer, &len);  if ('q' == recvBuf[0])  {  sendto(sockConnect, "q", strlen("q") + 1, 0, (SOCKADDR*)&addrInfoServer, len);  printf("聊天结束");  break;  }  sprintf(tempBuf, "%s 说:%s", inet_ntoa(addrInfoServer.sin_addr), recvBuf);  printf("%s\n", tempBuf);  }  // 关闭套接字
    closesocket(sockConnect);  WSACleanup();  }

3.其他

vc网络编程常用类型解析:  1. SOCKET 类型
SOCKET 是 socket 套接字类型,在 WINSOCK2.H 中有如下定义:
typedef unsigned u_int;
typedef u_int    SOCKET;
可知套接字实际上就是一个无符号整形,它将被 Socket 环境管理和使用。
套接字将被创建、设置、用来发送和接收数据,最后会被关闭。  2.WORD 类型、MAKEWORD、LOBYTE、HIBYTE 宏
WORD 类型是一个 16 位的无符号整型, 在 WTYPES.H 中被定义为:
typedef unsigned short  WORD;
其目的是提供两个字节的存储, 在 Socket 中这两个字节可以表示主版本号和副版本号。
使用 MAKEWORD 宏可以给一个 WORD 类型赋值。例如要表示主版本号 2, 副版本号 0,可以使用如下代码:
WORD wVersionRequested;
wVersionRequested   = MAKEWORD(2, 0);
注意低位内存存储主版本号 2, 高位内存存储副版本号 0,其值为 0x0002。
使用宏 LOBYTE 可以读取 WORD 的低位字节, HIBYTE 可以读取高位字节。  3.WSADATA 类型和 LPWSADATA 类型
WSADATA 类型是一个结构,描述了 Socket 库的一些相关信息,其结构定义如下:  typedef struct WSAData
{  WORD        wVersion;                                 WORD        wHighVersion;                             char        szDescription[WSADESCRIPTION_LEN + 1];    char        szSystemStatus[WSASYS_STATUS_LEN + 1];  unsigned short  iMaxSockets;  unsigned short  iMaxUdpDg;  char    FAR*    lpVendorInfo;
}WSADATA;
typedef WSADATA FAR*    LPWSADATA;  值得注意的是 wVersion 字段,存储了 Socket 的版本类型。LPWSADATA 是 WSADATA 的指针类型。
他们通过 Socket 的初始化函数 WSAStartup 读取出来。  ////

vc网络编程常用函数解析:  1. WSAStartup 函数
用于初始化 Socket 环境,函数原型:
int WSAStartup(WORD wVersionRequested,  LPWSADATA lpWSAData);
其返回值为整型,调用方式为 PASCAL (即标准类型,PASCAL 等于__stdcall),参数有两个,
第一个参数为 WORD 类型,指明了 Socket 的版本号,第二个参数为 LPWSADATA,指向一个用于存储 Socket 库信息的WSAStartup结构。
返回值:
返回值为0,则初始化成功,若不为0则为失败。  2.WSACleanup 函数
这是 Socket 环境的退出函数,函数原型:
int  WSACleanup (void);
返回值:
返回值为0表示成功,SOCKET_ERROR 表示失败。  3.socket 函数
socket 套接字的创建函数,函数原型:
SOCKET socket(int af, int type, int protocol  );
第一个参数为:int af,      代表网络地址族,目前只有一种取值有效,即 AF_INET, 代表 internet 地址族;
第二个参数为:int type,    代表网络协议类型, SOCK_DGRAM 代表 UDP 协议, SOCK_STREAM 代表 TCP 协议。
第三个参数为:int protocol,指定网络地址族特殊协议,目前无用,赋值0即可。
返回值:
返回值为 SOCKET, 若返回INVALID_SOCKET 则失败。  4.bind 函数
用于将套接字绑定到一个已知地址上,函数原型:
int bind(SOCKET s, const struct sockaddr FAR *name, int namelen);
第一个参数为:SOCKET s,            指定将被绑定的套接字。
第二个参数为:SOCKADDR_IN *name,   是一个sockaddr结构指针,该结构中包含了要绑定的地址和端口。
第三个参数为:int  namelen,         确定第二个参数的结构长度。  返回值:   成功返回0,失败返回SOCKET_ERROR。  ///

下面对其涉及的类型作一番解析:
sockaddr 类型:
sockaddr 类型是用来表示 Socket 地址的类型,同上面的 socketaddr_in 类型相比,sockaddr 的适用范围更广,
因为sockeaddr_in只适用于 TCP/IP 地址。sockaddr 的定义如下:
struct sockaddr
{  ushort  sa_family;  char    sa_data[14];
};
可知sockaddr 的16个字节,而sockaddr_in也有16个字节,所以sockaddr_in是可以强制类型转换为sockadddr的。
事实上也往往使用这种方法。  sockaddr_in 定义了socket发送和接收数据包的地址,其定义如下:
strucr  sockaddr_in
{  short       sin_family;  u_short      sin_port;  struct in_addr  sin_addr;  char        sin_zero[8];
};  其中 in_addr 定义如下:
struct in_addr
{  union  {  struct {u_char   s_b1, s_b2, s_b3, s_b4} S_un_b;  struct {u_short  s_w1, s_w2} S_un_w;  u_long S_addr;  }S_un;
};
首先阐述 in_addr 的信义。
很显然它是一个存储 ip 地址的联合体,有三种表达方式:
第一种用四个字节来表示IP地址的四个数字;
第二种用两个双字节来表示IP地址;
第三种用一个长整型来表示IP地址;
给 in_addr 赋值的一种最简单方法是使用 inet_addr 函数, 它可以把一个代表IP地址的字符串赋值
转换为in_addr类型。如:
addrServer.sin_addr = inet_addr("192.168.0.2");
其反函数是 inet_ntoa,可以把一个 in_addr 类型转换为一个字符串。
sockaddr_in的含义比in_addr的含义要广泛,其各个字段的含义和取值如下:
第一字段 short           sin_family,代表网络地址族,如前所述,只能取值AF_INET;
第二字段 u_short         sin_port,  代表IP地址端口,由程序员指定;
第三字段 struct in_addr  sin_addr,  代表IP地址;
第四个字段char sin_zero[8],是为了保证sockaddr_in与SOCKADDR类型的长度相等而填充进来的字段。  5.listen 函数
该函数让一个套接字在指定IP地址的指定端口处监听连接请求的到来,函数原型:
int listen(  SOCKET s,      int backlog  );
该函数使得一个进程可以接受其他进程的请求,从而成为一个服务器进程。
在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。
listen 函数一般在调用bind之后、调用accept之前调用。
返回值:  成功则返回0,失败返回SOCKET_ERROR,可以调用函数WSAGetLastError来取得错误代码。  6.accept函数
该函数从连接请求队列中获得连接信息,并创建新的套接字用于收发数据,实现服务器与客户端的通信。函数原型:
SOCKET accept(SOCKET s,  struct sockaddr FAR *addr,  int FAR *addrlen);
第一个参数:SOCKET          s,      监听套接字
第二个参数:struct sockaddr addr,   存储请求连接的客户端IP地址、端口信息
第三个参数:int             addrlen,第二个参数所占空间大小
返回值:
成功返回新套接字,失败返回错误信息  7.connect 函数
向指定的网络主机请求连接,函数原型:
int connect(SOCKET s, const struct sockaddr FAR *name, int namelen);
第一个参数:SOCKET           s,       客户端用于收发数据的套接字。
第二个参数:struct sockaddr  *name,   指定网络主机IP地址和端口号。
第三个参数:int              namelen, 第二参数长度
返回值:
成功返回0,失败返回-1。  8.sendto、recvfrom、send、recv函数
在 Socket 中有两套发送和接收函数。一是sendto 和recvfrom; 二是send 和 recv。
前一套在函数参数中要指明地址(UDP协议),
而后一套需要先将套接字和一个地址绑定,然后直接发送和接收,不需绑定地址。
函数原型:
int sendto(  SOCKET s, const char FAR *buf, int len, int flags, const struct sockaddr FAR *to,   int      tolen);
int recvfrom(SOCKET s,       char FAR* buf, int len, int flags, struct sockaddr FAR       *from, int FAR *fromlen);  int send(SOCKET s,const char FAR *buf,  int len, int flags);
int recv(SOCKET s,      char FAR *buf,  int len, int flags);  第一个参数: 套接字
第二个参数: 数据指针
第三个参数: 数据长度
第四个参数: 收发数据方式的标识,如果不需要特殊要求可以设置为0,其他值可参考MSDN;
第五个参数: 目标主机地址
第六个参数: 地址的长度  返回值:   运行成功则返回收发数据的字节数,失败返回SOCKET_ERROR  9.closesocket 函数
关闭套接字,函数原型:
int closesocket(  SOCKET s  );
返回值:  成功返回0,失败返回SOCKET_ERROR。

转载于:https://www.cnblogs.com/wuyuan2011woaini/p/5740975.html

MFC 网络编程 -- 总结相关推荐

  1. MFC 网络编程小结

    最近对MFC的网络编程方面研究了一下..现在想对学习过程中的问题和一些想法做下总结. 1.现说下socket(套接字)吧,初学者刚看到这个东西的时候一定觉得很神秘,我也一样,现在也只是有一点皮毛的理解 ...

  2. 糖儿飞教你学C++ Socket网络编程——2.本书目录

    项目1 网络编程的实现原理... 1 1.1 网络程序的类型与应用领域... 1 1.1.1 网络程序的类型... 1 1.1.2 网络程序的应用领域... 2 1.2 套接字及其种类... 4 1. ...

  3. MFC socket网络编程(流程示例)

    MFC socket网络编程(流程示例) 1.TCP流式套接字的编程步骤 在使用之前须链接库函数:工程->设置->Link->输入ws2_32.lib,OK! 服务器端程序: 1.加 ...

  4. 网络编程-基于MFC的仿QQ聊天室-2020

    基于MFC的仿QQ聊天室(2020) 有幸学习过网络编程的一些知识,出于对编程的热爱,把曾经的一次简单实践编程作业进行了自定义的完成. 编程所需: 编程工具为VS 2010,需要掌握MFC的基本操作以 ...

  5. 网络编程(三)---- MFC 仿QQ聊天软件

    今天来八一八,MFC的SOCKET 编程,利用CSocket实现一个基于TCP实现一个QQ聊天程序.你会发现,MFC要比WIN32 简单的多.但是如果你不理解具体API socket基础知识,你可能会 ...

  6. 孙鑫MFC笔记之十二--网络编程

    网络状况: ü多种通信媒介--有线.无线-- ü不同种类的设备--通用.专用-- ü不同的操作系统--Unix.Windows -- ü不同的应用环境--固定.移动-- ü不同业务种类--分时.交互. ...

  7. Linux C++/Java/Web/OC Socket网络编程

    一,Linux C++ Socket网络编程 1.什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制 ...

  8. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  9. [windows网络编程]tcp/udp编程初步详解-转

    #pragma comment (lib,"ws2_32.lib") #include <Winsock2.h> #include <stdio.h> 如你 ...

最新文章

  1. 微信小程序外卖增长402%,茶饮下单最活跃
  2. MVC开发人员必备的五大工具
  3. .Net程序内存泄漏解析
  4. HDFS概述(2)————Block块大小设置
  5. ubuntu18的网关ip在哪里配_技术|如何在 Ubuntu 18.04 LTS 中配置 IP 地址
  6. 使用HTML5技术控制电脑或手机上的摄像头(转载)
  7. 商城管理系统源码 商城APP源码 电子商城源码
  8. GIS数据处理与应用开发一站式解决方案
  9. Git版本控制管理教程(一):介绍
  10. 英特尔芯片组系列 服务器,英特尔主板现在有几种架构,分别都是什么。都是对应什么系列CPU安装最好。说的越详细越好...
  11. 第五届阿里天池中间件比赛经历分享
  12. GIT 中如何打标签(git tag)
  13. 数据库常用操作语句总结
  14. 如何将刷题的效率提升10倍
  15. Windows、Linux系统常用CMD命令大全
  16. PTA字符串关键字的散列映射 (哈希表)
  17. Golang 函数定义 不定数目参数定义 多个输入参数函数 (...) 不定参数 可变参数 定义
  18. FPGA设计中,Vivado 调用IP核详细操作步骤
  19. UnityVR--小程序7--坦克对战
  20. 【陈工笔记】【复盘】# 服务器集群使用方式 #

热门文章

  1. Scala模式匹配:对规则进行匹配
  2. 在word上写博客直接发到CSDN博客
  3. oracle用户名无法登陆,sysdba却可以登陆
  4. 如何成为linux内核维护人员,Linux内核维护人员Greg Kroah-Hartman拒绝明尼苏达大学的道歉...
  5. paddlepaddle测试安装_PaddlePaddle升级解读 | 十余行代码完成迁移学习,PaddleHub实战篇...
  6. 【已解决】linux redhat 6 如何打开防火墙中的某个端口?例如:5900端口
  7. String类和StringBuffer类的区别
  8. 1.3.3 系统调用(执行过程、访管指令、库函数与系统调用)
  9. ISP、主机之间的通信方式、电路交换和分组交换、时延
  10. 南邮 Android 课程设计,南邮大四课程设计.doc