Windows平台网络通信

参考文章:https://blog.youkuaiyun.com/only_write_bug/article/details/148590269?spm=1001.2014.3001.5502https://blog.youkuaiyun.com/only_write_bug/article/details/148590269?spm=1001.2014.3001.5502

inet_addr()和inet_aton()函数详解-优快云博客https://blog.youkuaiyun.com/only_write_bug/article/details/148604927?spm=1001.2014.3001.5502 地址位与数据位、大端和小端字节序、字节序转换-优快云博客https://blog.youkuaiyun.com/only_write_bug/article/details/148603350?spm=1001.2014.3001.5502

一、环境配置

        我们使用Visual Studio 2008版本。

        1、导入头文件winsock2.h

        2、链接ws2_32.lib库

打开项目的属性页,选中“配置属性”-->"输入"—>“附加依赖项”。也可Alt+F7打开“属性页”。

在右边空白处填入ws2_32.lib。之后我们只需要在源文件中添加头文件winsock2.h即可。

二、Winsock的初始化

        进行Winsock编程时,首先调用WSAStartup函数,设置程序中要使用的Winsock版本。并初始化库。

#include <winsock2.h>

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSData);
//成功返回0,失败返回非0的错误码
//wVersionRequested:选中的Winsock版本信息
//lpWSData:WSADATA结构体变量的地址值
/*  wVersionRequested:若传递0x0201,表示主版本号1,副版本号2.   高八位为副版本号,低八位为主版本号。
    也可借助MAKEWORD宏函数构建版本信息
    MAKEWORD(1,2):主版本号1,副版本号2,返回0x0201.
    MAKEWORD(2,2):主版本号2,副版本号2,返回0x0202.
*/


//使用示例
int main()
{
    WSADATA wsaData;//定义WSADATA 结构体
    //调用初始化函数
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    {
        printf("WSAStartup error!\n");
        return 0;
       }
    return 0;
}

三、基于Windows的套接字相关函数       

#include <winsock2.h>

SOCKET socket(int af, int type, int protocol);
/* 成功返回套接字句柄, 失败返回INVALID_SOCKET*/

int bind(SOCKET s, const struct sockaddr*name, int namelen);
/* 与Linux系统的bind函数相同,实现IP和端口分配。 成功返回0, 失败返回SOCKET_ERROR*/

int listen(SOCKET s, int backlog);
/* 与Linux系统的Listen函数相同,实现接收客户端连接功能, 成功返回0,失败返回SOCKET_ERROR*/

SOCKET accept(SOCKET s, struct sockaddr*addr, int *addrLen);
/* 与Linux系统的accept函数相同,实现受理客户端连接请求,成功返回套接字句柄,失败返回INVALID_SOCKET*/

int connect(SOCKET s, const struct sockaddr*addr, int addrLen);
/* 与Linux系统的connect函数相同, 实现从客户端发送连接请求的功能,成功返回0,失败返回SOCKET_ERROR */

int closesocket(SOCKET s);
/*和Linux系统的close函数相同,实现关闭套接字连接,成功返回0,失败返回SOCKET_ERROR */

int send(SOCKET s, const char*buf, int len, int flags);
/*成功返回0,失败返回SOCKET_ERROR */
/*
    s:传输数据的SOCKET套接字句柄
    buf:要传输的数据的地址值
    len:要传输的数据大小,字节数
    flags:传输数据时用到的多种选项,一般为 0 即可
*/

int recv(SOCKET s, const char*buf, int len, int flags);
/*成功返回0,失败返回SOCKET_ERROR */
/*
    s:接收数据的SOCKET套接字句柄
    buf:要保存数据的地址值
    len:要接收的最大数据大小,字节数
    flags:接收数据时用到的多种选项,一般为 0 即可
*/

四、服务端与客户端创建示例

        一、Windows网络通信客户端创建示例

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

int main()
{
    char buff[100] = "hello, I am Client";
    char recvbuff[1024] = {0};//接收信息
    //1、初始化WSADATA结构体对象
    WSADATA wsaData;
    //2、初始化WSAStartup
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    {
        printf("WSAStartup init error!\n");
        return 0;
    }
 
    //3、初始化套接字 TCP套接字SOCK_STREAM,PF_INET:IPV4互联网协议族
    SOCKET cli_socket;
    cli_socket = socket(PF_INET, SOCK_STREAM, 0);
    if(cli_socket == INVALID_SOCKET)
    {
        printf("cli_socket init error!\n");
        return 0;
    }
    //4、初始化结构体
    SOCKADDR_IN ser_addr;//服务器IP和端口等信息
    memset(ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_addr.s_addr = inet_addr("192.168.1.110");//指定服务器IP
    ser_addr.sin_port = htons(8888);//指定服务器端口
    int ser_addrLen = sizeof(ser_addr);

    //5、与服务器建立连接
    if(connect(cli_socket, (SOCKADDR*)&ser_addr, ser_addrLen) == SOCKET_ERROR)
    {
        printf("connect init error!\n");
        return 0;
    }
    //6、接收发送信息
    int recvlen = 0;    //接收字节长度
    //可添加循环退出标志  bool flag = true;
    while(1)
    {
        //可添加循环判断
        /*
        if(!flag)
        {break;}
        */
        memset(recvbuff, 0, sizeof(recvbuff));//先清空
        recvlen = recv(cli_socket, recvbuff, sizeof(recvbuff)-1, 0);
        if(recvlen > 0)
        {    
               printf("recvbuff is %s\n",recvbuff);
               //发送数据到服务器
               if(send(cli_socket, buff, sizeof(buff), 0) == SOCKET_ERROR)
               {
                   printf("socket send information error!\n");
                   return 0;
               }
               //flag = false;
        }
    }
    closesocket(cli_socket);//关闭套接字
    WSACleanup();//清除WSA
    return 0;
}

        二、Windows网络通信服务端创建示例

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

int main()
{
    char buff[100] = "hello, I am Server";
    char recvbuff[1024] = {0};//接收信息
    //1、初始化WSADATA结构体对象
    WSADATA wsaData;
    //2、初始化WSAStartup
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    {
        printf("WSAStartup init error!\n");
        return 0;
    }
 
    //3、初始化套接字 TCP套接字SOCK_STREAM,PF_INET:IPV4互联网协议族
    SOCKET ser_socket;//服务器监听套接字
    ser_socket = socket(PF_INET, SOCK_STREAM, 0);
    if(ser_socket == INVALID_SOCKET)
    {
        printf("ser_socket init error!\n");
        return 0;
    }
    //4、初始化结构体
    SOCKADDR_IN ser_addr;//服务器IP和端口等信息
    memset(&ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_addr.s_addr = INADDR_ANY;//指定服务器IP
    ser_addr.sin_port = htons(8888);//指定服务器端口
    int ser_addrLen = sizeof(ser_addr);
    //5、绑定自身端口和IP信息
    if(bind(ser_socket, (SOCKADDR*)&ser_addr, ser_addrLen) == SOCKET_ERROR)
    {
        printf("bind init error!\n");
        return 0;
    }
    //6、监听连接对象
    if(listen(ser_socket, 5) == SOCKET_ERROR)
    {
        printf("Listen init error!\n");
        return 0;
    }

    //7、接收连接请求建立连接
    SOCKET cli_socket;//客户端通信套接字
    SOCKADDR_IN cli_addr;//客户端IP和端口等信息
    int cli_addrLen = sizeof(cli_addr);
    cli_socket = accept(ser_socket, (SOCKADDR*)&cli_addr, &cli_addrLen);
    if(cli_socket == INVALID_SOCKET)
    {
        printf("accept client error!\n");
        return 0;
    }
    
    //8、发送信息,接收信息
    send(cli_socket, buff, sizeof(buff), 0);
    int recvNum = 0;
    while(1)
    {
         memset(recvbuff, 0, sizeof(recvbuff));
         recvNum = recv(cli_socket, recvbuff, sizeof(recvbuff)-1, 0);
         if(recvNum > 0)
         {    
               printf("recvbuff is %s\n",recvbuff);
               // 添加退出条件示例
               if(strcmp(recvbuff, "exit") == 0) break;
         }    
    }
    closesocket(cli_socket);//关闭套接字
    closesocket(ser_socket);//关闭套接字
    WSACleanup();//清除WSA
    return 0;
}

        三、服务器部分添加多线程实现

// 使用多线程或select()处理多个客户端
while(1) {
    SOCKET new_client = accept(...);
    CreateThread(NULL, 0, ClientHandler, (LPVOID)new_client, 0, NULL);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值