windows平台下socket编程相关TCP和UDP的介绍

TCP的会产生三次握手和四次挥手,这在我的原来的博客中也描述过就不多描述了

TCP/UDP位于传输层

  • 传输层:主要负责不同主机间进程之间的通信服务。
  • 端口:计算机进程的标识序号,用于提供不同主机之间通信服务的标识
    • 0 ~ 1023称为系统端口号
    • 1024 ~ 49151称为用户端口号
    • 19152 ~ 65535称为动态端口号
  • TCP协议:在两台主机之间创建持久性的连接,提供可靠数据流传输,数据准确,多用于保证数据不丢失的场合,如发送邮件缺点是要建立连接效率没有udp高
  • UDP协议:一个轻量级的协议,封装数据并将其从一台主机的一个端口发送到另一台主机的端口,优点效率快,多用于如视频传输之类不在乎一两个包的丢失的场合
  • 缺点:不保证数据传输和准确到达。不可靠

 

相关API

TCP创建服务器的步骤

1创建Socket

windos平台必须初始化socket: 

WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
  1. SOCKET socket(int af, int type, int protocol)
    • 参数af指地址族:
      • AF_NET:IPV4协议
      • AF_NET6:IPV6协议
    • TYPE指发送的数据类型
      • SOCK_STREAM:有序可靠的数据段(TCP协议)
      • SOCK_DGRAM:离散的报文(UDP协议)
    • Protocol指协议类型
      • IPPROTO_UDP:UDP协议
      • IPPROTO_TCP:TCP协议
      • 如果填0,根据前两个参数选取默认协议
  2. 绑定SOCKET:int PASCAL FAR bind( SOCKET sockaddr, const struct sockaddr FAR* my_addr,int addrlen);

     

    //2.绑定端口
      sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(5566);
      addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
      //addr.sin_addr.S_un.S_addr = ADDR_ANY;  //任何地址
      int result = bind(socket_, (sockaddr*)&addr, sizeof(addr));
      if (result == SOCKET_ERROR)
      {
        reportError("bind\n");
        return;
      }

     

    • Socket地址存储结构体
- struct sockaddr //标准库
{
    uint16_t sa_family; //地址族
    char sa_data[14]; // 
}

struct sockaddr_in  //微软提供
{
    short sa_family; //指代协议族,在socket编程中只能是AF_INET
    uint16_t sin_port; // 存储端口号(使用网络字节顺序)
    struct in_addr sin_addr; //存储IP地址,使用in_addr这个数据结构
    char sin_zero[8]; //是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
}
  • 2设置并行最大监听数,监听的是客户端并发的最大数量
int result = listen(s, SOMAXCONN);//SOMAXCONN宏为默认最大监听数

if (result < 0)
{
    reportError(_T("listen"));
    return 0;
}
showMsg(_T("listen ok"));
  • 3服务器接受客户端连接请求
sockaddr_in caddr;
int len = sizeof(addr);
int cs = accept(s, (sockaddr*)&caddr, &len); // s为请求连接客户端的socket

if (cs < 0) 
{
    reportError(_T("accept"));
    break;
}
  • 4接收消息
//注意send的第三个参数写自己要实际发送的长度,len大了的话会把多余的数据发送过去
int result = send(s, buffer, strlen(buffer) + 1, 0);

if (result < 0)
{
    reportError(_T("send"));
    return 0;
}
showMsg(_T("send ok"));

  • 5发送消息
//注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的
//数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的
int result = recv(s, buffer, sizeof(buffer), 0);

if (result < 0)
{
    reportError(_T("recv"));
    return 0;
}
showMsg(_T("recv ok"));
  • 通过客户端socket获取地址信息
int cs = (int)lpParameter; //客户端socket
sockaddr_in caddr;
int len = sizeof(caddr);

//客户端连接 通过socket获取地址信息
if (getpeername(cs, (sockaddr*)&caddr, &len) < 0) 
{
    reportError(_T("getpeername"));
    return 0;
}

TCP创建客户端步骤

相关api

1创建socket

2连接connect

 //连接
  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(58888);
  if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) < 0) 
  {
    ReportError("inet_pton");
    return 0;
  }
  int nRet = connect(g_nSocket, (sockaddr*)&addr, sizeof(addr));
  if (nRet < 0)
  {
    ReportError("connect");
    return 0;
  }

3发送 send

4接收recv

TCP粘包问题解决 

粘包:因为TCP是字节流的传输方式,没有边界,所以在网络传输快的情况下,会把两个包粘成一个包发送,网络慢的话有可能只发送半个包,剩下的半个和下一个包一起发过来

 一般解决方式:在包头加上一个包体的长度,这样的话无论是哪种情况,我只有读到这个长度才结束,这样收到的包就是完整的,也可以实现包的拆分,下一个包的位置就是首地址加上上一个包的长度就可以找到了

 

UPD创建服务器的步骤

1初始化后创建socket

2绑定bind

3发送sendto

 CHAT_HEAD_INFO sendHead;
 sendHead.version = 1;
 sendHead.len = 0;
 sendHead.cmd = CHAT_LOGIN_ERROR;
 //发送
 int result = sendto(socket_, (char*)&sendHead, sizeof(sendHead), 0, (sockaddr*)&caddr, 
 sizeof(caddr));
 if (result <= 0)
 {
   reportError("sendto");
   return -1;
 }

4接收recvfrom

 sockaddr_in caddr;
  int len = sizeof(caddr);
  CHAT_HEAD_INFO head;
  int result;
  char *buffer = NULL;


  //接受消息
  result = recvfrom(socket_, (char*)&head, sizeof(head), 0, (sockaddr*)&caddr, &len);
  if (result <= 0)
  {
    reportError("recvfrom\n");
    return 0;
  }

UPD创建客户端的步骤

1初始化后创建socket

2发送接收sendto  recvfrom

 

 

数据传输自定义的协议分为二进制协议和文件协议

文本协议

  1. 优势
    • 协议自由,方便修改
  2. 劣势

    例子如下 

    • 解析数据过程占用时间过长
使用特定分隔符号标识每一行数据
//    command:sayto \n
//    lenth : 6      \n
//    source id : 100 \n
//    dest   id : 200\n
//    msg : hello

//按对应格式,格式化字符串后打包整个数据并输出
sprintf_s(szMsg, sizeof(buffer),
    "cmd:sayto\n"
    "sourceid:%d\n"
    "deskid:%d\n"
    "len:%d\n"
    "msg:"
    "%s", nSourceID, nDeskID, nlength, szBuff);

int result = send(cinfo.ucs, szMsg, strlen(szMsg) + 1, 0);

二进制协议

  1. 优势
    • 传输解析速度快
  2. 劣势

    例子如下 

    • 扩展性不好

例子

 

enum CHAT_COMMAND
{
  CHAT_LOGIN,       //登录
  CHAT_ACK,         //确认
  CHAT_LOGIN_OK,    //成功
  CHAT_LOGIN_ERROR, //失败
  CHAT_ALL_USER,    //通知所有用户
  CHAT_LOGOUT,       //登录
  CHAT_SAY_ALL,       //对所有人说
  CHAT_SAY_TO,       //对人说
  CHAT_HEARTBEAT,    //心跳包
};

struct  CHAT_HEAD_INFO
{
  int version;
  int cmd;
  int len;
};



CHAT_HEAD_INFO sendHead;
sendHead.version = 1;
sendHead.len = 0;
sendHead.cmd = CHAT_LOGIN_ERROR;
int result;
result = send(nScoket,(char*)&sendHead, sizeof(sendHead), 0);
if (result <= 0)
{
  reportError("send");
  return -1;
}

 

1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资项目码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值