孙鑫vc++ 14 Socket

本文介绍了套接字的基本类型包括流式、数据报和原始套接字,并详细解释了网络字节序的概念及其重要性。此外,还提供了基于TCP和UDP协议的客户端/服务器模式的具体实现步骤,以及使用相关函数进行IP地址和端口号转换的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、套接字类型

1.流式套接字(基于TCP协议)

2.数据报套接字(基于UDP协议)

3.原始套接字(一般不常用)

二、网络字节序

不同的计算机存放字节的顺序不同,基于Intel的CPU,即我们常用的PC机采用的是低位先存。为了确保数据的正确性,在网络协议中需要指定网络字节顺序,TCP/IP协议使用16位整数和32位整数的高位先存格式。在网络中不同的主机进行通信的时候,要采用统一的网络字节顺序。

三、套接字使用方法

1.基于TCP协议的c/s模式的socket应用

服务器端:

(1)创建用于监听的socket  SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);

(2)绑定到固定的计算机上  bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

(3)在服务器所在的计算机上监听  listen(sockSrv,5);

(4)等待客户端连接并创建用于聊天通信的socket  SOCKET sockClient = accept(sockSrv,(SOCKADDR*)&addrClient,&len);

(5)向客户端发送数据  send(sockClient,sendBuf,strlen(sendBuf)+1,0);

(6)接收客户端发送的数据 recv(sockClient,recvBuf,100,0);

(7)关闭socket  closesocket(sockClient);

(8)服务器端用于监听的socket需要一直开启

客户端:

(1)创建用于聊天通信的socket  SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);

(2)连接服务器端  connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

(3)接收服务器端传来的数据 recv(sockClient,recvBuf,100,0);

(4)向服务器端发送数据  send(sockClient,"This is zhangsan",strlen("This is zhangsan")+1,0);

(5)关闭socket  closesocket(sockClient);

 

2.基于UDP协议的c/s模式的socket应用

服务器端:

(1)创建用于监听的socket  SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);

(2)绑定到固定的计算机上  bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

(3)接收客户端传来的数据  recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&length);

(4)向客户端发送数据  sendto(sockSrv,"This is zhangsan",strlen("This is zhangsan")+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

(5)关闭socket  closesocket(sockSrv);

客户端:

(1)创建用于聊天通信的socket  SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);

(2)向服务器端发送数据  sendto(sockClient,"This is zhangsan",strlen("This is zhangsan")+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

(3)接收服务器端传来的数据  recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)&addrSrv,&length);

(4)关闭socket closesocket(sockClient);

 

四、几个需要注意的函数

(1)IP地址相关,inet_addr()和inet_ntoa()

用法:inet_addr(“127.0.0.1”);将点分十进制记的IP地址转换成为网络字节序的S_addr类型的IP地址

           inet_ntoa(addrClient.sin_addr);将网络字节序的S_addr类型的IP地址转换成为点分十进制记的IP地址

(2)端口号相关,htonl()和htons()

用法:htonl(INADDR_ANY);把一个u_long类型的值从主机字节序转换成为TCP/IP网络字节顺序

           htons(6000);把一个u_short类型的值从主机字节序转换成为TCP/IP网络字节顺序

           INADDR_ANY这个宏的值就是0,转换之后仍然是0

 

五、网络聊天室程序(基于UDP协议)

1.服务器端:(在工程,属性,linker,command line中使用了ws2_32.lib)

#include <WinSock2.h>
#include <stdio.h>

void main()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;

 wVersionRequested = MAKEWORD(1,1);

 err = WSAStartup(wVersionRequested,&wsaData);

 if (err != 0)
 {
  return;
 }

 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
 {
  WSACleanup();
  return;
 }

 SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);

 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 addrSrv.sin_port = htons(6000);
 addrSrv.sin_family = AF_INET;

 bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

 SOCKADDR_IN addrClient;
 int length = sizeof(SOCKADDR);
 char recvBuf[100];
 char tempBuf[100];
 char sendBuf[100];

 while(1)
 { 
  recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&length);
  if ('q' == recvBuf[0])
  {
   sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,sizeof(SOCKADDR));
   printf("chat end!");
   break;
  }

  sprintf(tempBuf,"%s say: %s",inet_ntoa(addrClient.sin_addr),recvBuf);
  printf("%s\n",tempBuf);
  printf("input data:\n");
  gets(sendBuf);
  sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,sizeof(SOCKADDR));
 }

 closesocket(sockSrv);
 WSACleanup();
}

 

2.客户端:(在工程,属性,linker,command line中使用了ws2_32.lib)

#include <WinSock2.h>
#include <stdio.h>

void main()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;

 wVersionRequested = MAKEWORD(1,1);

 err = WSAStartup(wVersionRequested,&wsaData);

 if (err != 0)
 {
  return;
 }

 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
 {
  WSACleanup();
  return;
 }

 SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);

 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 addrSrv.sin_port = htons(6000);
 addrSrv.sin_family = AF_INET;

 SOCKADDR_IN addrClient;

 char recvBuf[100];
 char tempBuf[100];
 char sendBuf[100];

 while (1)
 {
  printf("input data:");
  gets(sendBuf);
  sendto(sockClient,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

  recvfrom(sockClient,recvBuf,100,0,&addrClient)
 }
}


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值