socket网络编程——win32平台和linux平台

简介: socket网络编程——win32平台和linux平台

文章目录

win32平台

调用步骤

代码示例:

服务器端

客户端

遇到的问题及解决方式

1.打开两个qt IDE运行出现问题:

2.使用VS2019编译客户端出现问题:


win32平台

在VC中进行WINSOCK的API编程开发的时候,需要在项目中使用下面的三个文件,否则会出现编译错误。


1.WINSOCK.H: 这是WINSOCK API的头文件,需要包含在项目中。


2.WSOCK32.LIB: WINSOCK API连接库文件。在使用中,一定要把它作为项目的非缺省的连接库包含到项目文件中去。


3.WINSOCK.DLL: WINSOCK的动态连接库,位于WINDOWS的安装目录下


服务器端操作 socket(套接字)


调用步骤

1.在初始化阶段调用WSAStartup()


此函数在应用程序中初始化Windows Sockets DLL ,只有此函数调用成功后,应用程序才可以再调用其他Windows Sockets DLL中的API函数。在程式中调用该函数的形式如下:WSAStartup((WORD)((1<<8|1), (LPWSADATA)&WSAData),其中(1<<8|1)表示我们用的是WinSocket1.1版本,WSAata用来存 储系统传回的关于WinSocket的资料。


2、建立Socket


初始化WinSock的动态连接库后,需要在 服务器端建立一个监听的Socket,为此可以调用Socket()函数用来建立这个监听的Socket,并定义此Socket所使用的通信协议。此函数 调用成功返回Socket对象,失败则返回INVALID_SOCKET(调用WSAGetLastError()可得知原因,所有WinSocket 的API函数都可以使用这个函数来获取失败的原因)。


SOCKET PASCAL FAR socket( int af, int type, int protocol )
参数: 
  af:目前只提供 PF_INET(AF_INET);
  type:Socket 的类型 (SOCK_STREAM、SOCK_DGRAM);
  protocol:通讯协定(如果使用者不指定则设为0);


如果要建立的是遵从TCP/IP协议的socket,第二个参数type应为SOCK_STREAM,如为UDP(数据报)的socket,应为SOCK_DGRAM。


3、绑定端口


接下来要为服务器端定义的这个监听的Socket指定一个地址及端口(Port),这样客户端才知道待会要连接哪一个地址的哪个端口,为此我们要调用bind()函数,该函数调用成功返回0,否则返回SOCKET_ERROR。


int PASCAL FAR bind( SOCKET s, const struct sockaddr FAR *name,int namelen );
参 数: 
  s:Socket对象名;
  name:Socket的地址值,这个地址必须是执行这个程式所在机器的IP地址;
  namelen:name的长度;


如果使用者不在意地址或端口的值,那么可以设定地址为INADDR_ANY,及Port为0,Windows Sockets 会自动将其设定适当之地址及Port (1024 到 5000之间的值)。此后可以调用getsockname()函数来获知其被设定的值。


4、监听


当服务器端的Socket对象绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。listen()函数使服务器端的Socket 进入监听状态,并设定可以建立的最大连接数(目前最大值限制为 5, 最小值为1)。该函数调用成功返回0,否则返回SOCKET_ERROR。


int PASCAL FAR listen( SOCKET s, int backlog );
参 数: s:需要建立监听的Socket;
backlog:最大连接个数;


服务器端的Socket调用完listen()后,如果此时客户端调用connect()函数提出连接申请的话,Server 端必须再调用accept() 函数,这样服务器端和客户端才算正式完成通信程序的连接动作。为了知道什么时候客户端提出连接要求,从而服务器端的Socket在恰当的时候调用 accept()函数完成连接的建立,我们就要使用WSAAsyncSelect()函数,让系统主动来通知我们有客户端提出连接请求了。该函数调用成功 返回0,否则返回SOCKET_ERROR。


int PASCAL FAR WSAAsyncSelect( SOCKET s, HWND hWnd,unsigned int wMsg, long lEvent );
参数: 
  s:Socket 对象;
  hWnd :接收消息的窗口句柄;
  wMsg:传给窗口的消息;
  lEvent:被注册的网络事件,也即是应用程序向窗口发送消息的网路事件,该值为下列值FD_READ、FD_WRITE、FD_OOB、 FD_ACCEPT、FD_CONNECT、FD_CLOSE的组合,
  各个值的具体含意为
  FD_READ:希望在套接字S收到数据时收到消 息;
  FD_WRITE:希望在套接字S上可以发送数据时收到消息;
  FD_ACCEPT:希望在套接字S上收到连接请求时收到消息;
  FD_CONNECT: 希望在套接字S上连接成功时收到消息;
  FD_CLOSE:希望在套接字S上连接关闭时收到消息;
  FD_OOB:希望在套接字S上收到带外数据时收到消息。 
具体应用时,wMsg应是在应用程序中定义的消息名称,而消息结构中的lParam则为以上各种网络事件名称。所以,可以在窗口处理自定义消息函数中使用 以下结构来响应Socket的不同事件:
  switch(lParam) 
  {
  case FD_READ:
    break;
  case FD_WRITE:
    break;
  }


5、服务器端接受客户端的连接请求


当Client提出连接请求时,Server 端hwnd视窗会收到Winsock Stack送来我们自定义的一个消息,这时,我们可以分析lParam,然后调用相关的函数来处理此事件。为了使服务器端接受客户端的连接请求,就要使用 accept() 函数,该函数新建一Socket与客户端的Socket相通,原先监听之Socket继续进入监听状态,等待他人的连接要求。该函数调用成功返回一个新产 生的Socket对象,否则返回INVALID_SOCKET。


SOCKET PASCAL FAR accept( SCOKET s, struct sockaddr FAR *addr,int FAR *addrlen );
参数:
  s:Socket的识别码;
  addr:存放来连接的客户端的地址;
  addrlen:addr的长度


6、结束 socket 连接


结束服务器和客户端的通信连接是很简单的,这一过程可以由服务器或客户机的任一端启动,只要调用closesocket()就可以了,而要关闭 Server端监听状态的socket,同样也是利用此函数。另外,与程序启动时调用WSAStartup()憨数相对应,程式结束前,需要调用 WSACleanup() 来通知Winsock Dll释放Socket所占用的资源。这两个函数都是调用成功返回0,否则返回SOCKET_ERROR。


int PASCAL FAR closesocket( SOCKET s );
参数:
  s:Socket 的识别码;
int PASCAL FAR WSACleanup( void );
参数: 无


代码示例:

服务器端

  • server.c
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
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_STREAM,0);
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000);
 bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));// 绑定端口
 listen(sockSrv,5);
 SOCKADDR_IN addrClient;// 连接上的客户端ip地址
 int len=sizeof(SOCKADDR);
 while(1)
 {
  SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);// 接受客户端连接,获取客户端的ip地址
  char sendBuf[50];
  sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClient.sin_addr));// 组合消息发送出去
  send(sockConn,sendBuf,strlen(sendBuf)+1,0);// 发送消息到客户端
  char recvBuf[50];
  recv(sockConn,recvBuf,50,0);// 接受客户端消息
  printf("%s\n",recvBuf);
  //closesocket(sockConn);//断开连接
 }
}


客户端

  • client.c
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
void main()
{
    WORD wVersionRequested;
    WSADATA wsaData;//WSAata用来存储系统传回的关于WinSocket的资料。
    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_STREAM,0);// AF_INET ..tcp连接
    //初始化连接与端口号
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//本机地址,服务器在本机开启
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(6000);// 设置端口号
    connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//连接服务器
    char recvBuf[50];
    recv(sockClient,recvBuf,50,0);//接受数据
    printf("%s\n",recvBuf);
    send(sockClient,"hello",strlen("hello")+1,0);//发送数据
    closesocket(sockClient);//关闭连接
    WSACleanup();
}


遇到的问题及解决方式

1.打开两个qt IDE运行出现问题:

Cannot retrieve debugging output.
  • 描述:Qt Creator的问题,两个IDE同时打开,后打开的会出现这个情况
  • 解决方式:只打开一个IDE。

2.使用VS2019编译客户端出现问题:

error C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_D


  • 描述:在VS2013以后的版本中,增加了inet_pton()、InetPton()之类的新函数,用于IP地址在“点分十进制”和“二进制整数”之间转换,并且能够处理ipv4和ipv6。而inet_addr是老函数,高版本VS在编译时默认使用了新函数,所以会报该错误。
  • 解决方式一:
  • 用所提示的新函数代替inet_addr函数。
  • 解决方法二:
  • 修改VS配置,告诉它我就要旧函数
  • 1.修改方法:项目 -> 属性 -> C/C++ ->常规->SDL检查,将“是”改为“否”,即可。
  • 2.文件的属性页 -> “预处理器” -> 将“_CRT_SECURE_NO_WARNINGS”加上


相关文章
|
2月前
|
安全 物联网 物联网安全
量子通信网络:安全信息交换的新平台
【10月更文挑战第6天】量子通信网络作为一种全新的安全信息交换平台,正逐步展现出其独特的优势和巨大的潜力。通过深入研究和不断探索,我们有理由相信,量子通信网络将成为未来信息安全领域的重要支柱,为构建更加安全、高效、可靠的信息社会贡献力量。让我们共同期待量子通信网络在未来的广泛应用和美好前景!
|
1月前
|
域名解析 网络协议 安全
|
2月前
|
运维 监控 网络协议
|
1月前
|
存储 Ubuntu Linux
2024全网最全面及最新且最为详细的网络安全技巧 (三) 之 linux提权各类技巧 上集
在本节实验中,我们学习了 Linux 系统登录认证的过程,文件的意义,并通过做实验的方式对 Linux 系统 passwd 文件提权方法有了深入的理解。祝你在接下来的技巧课程中学习愉快,学有所获~和文件是 Linux 系统登录认证的关键文件,如果系统运维人员对shadow或shadow文件的内容或权限配置有误,则可以被利用来进行系统提权。上一章中,我们已经学习了文件的提权方法, 在本章节中,我们将学习如何利用来完成系统提权。在本节实验中,我们学习了。
|
1月前
|
Kubernetes 网络协议 Python
Python网络编程:从Socket到Web应用
在信息时代,网络编程是软件开发的重要组成部分。Python作为多用途编程语言,提供了从Socket编程到Web应用开发的强大支持。本文将从基础的Socket编程入手,逐步深入到复杂的Web应用开发,涵盖Flask、Django等框架的应用,以及异步Web编程和微服务架构。通过本文,读者将全面了解Python在网络编程领域的应用。
31 1
|
2月前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
29 1
|
2月前
|
消息中间件 监控 网络协议
Python中的Socket魔法:如何利用socket模块构建强大的网络通信
本文介绍了Python的`socket`模块,讲解了其基本概念、语法和使用方法。通过简单的TCP服务器和客户端示例,展示了如何创建、绑定、监听、接受连接及发送/接收数据。进一步探讨了多用户聊天室的实现,并介绍了非阻塞IO和多路复用技术以提高并发处理能力。最后,讨论了`socket`模块在现代网络编程中的应用及其与其他通信方式的关系。
166 3
|
2月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
3月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
101 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
2月前
|
网络协议 Linux 网络性能优化
Linux基础-socket详解、TCP/UDP
综上所述,Linux下的Socket编程是网络通信的重要组成部分,通过灵活运用TCP和UDP协议,开发者能够构建出满足不同需求的网络应用程序。掌握这些基础知识,是进行更复杂网络编程任务的基石。
147 1