vc++实现的tcp socket客户端和服务端示例

下面是针对“vc++实现的tcp socket客户端和服务端示例”的详细攻略:

一、什么是TCP Socket?

TCP(Transmission Control Protocol)是“传输控制协议”的缩写。它是一种基于连接的、可靠的、面向字节流的传输层协议,主要用于Internet上的数据传输。

Socket是指“套接字”,是一个软件API(Applications Programming Interface),是内核提供的通信机制,并且也是实现网络通信的一个标准。

二、实现TCP Socket客户端和服务端的步骤及对应代码

下面我们将分别介绍实现TCP Socket客户端和服务端的步骤及对应代码。

1. 实现TCP Socket客户端流程

  1. 创建Socket

首先,我们需要在客户端中创建一个Socket,代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    WSADATA wsadata;
    SOCKET sockClient;
    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        return -1;
    }

    sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockClient < 0)
    {
        return -1;
    }
    return 0;
}

在这段代码中,我们使用了WinSock2库中的socket函数来创建Socket。由于TCP是一种面向连接的协议,因此我们在创建Socket时需要指定协议类型(IPPROTO_TCP)和Socket类型(SOCK_STREAM)。

  1. 建立连接

建立连接的过程需要使用到connect函数。connect函数接收服务端地址,用于与服务端建立连接。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

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

    if (connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) < 0)
    {
        return -1;
    }

    ...
}

在这段代码中,我们首先定义了服务端的地址(包括端口号和IP地址),然后使用connect函数对Socket和服务端进行连接。

  1. 发送和接收数据

连接建立成功后,我们可以使用send函数来发送数据,使用recv函数来接收数据。代码如下:


#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    char buf[] = "Hello World!";
    send(sockClient, buf, strlen(buf), 0);

    char recvBuf[100];
    int len = recv(sockClient, recvBuf, 100, 0);

    ...

    return 0;
}

在这段代码中,我们使用send函数发送了一个字符串(Hello World!),然后使用recv函数接收服务端返回的数据。可以看到,send和recv函数分别需要传入Socket、发送/接收的数据和数据长度等参数。

  1. 关闭Socket

最后,在完成客户端的所有操作后,我们需要使用closesocket函数来关闭Socket。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    closesocket(sockClient);
    WSACleanup();

    return 0;
}

2. 实现TCP Socket服务端流程

  1. 创建Socket

与客户端类似,我们首先需要在服务端中创建一个Socket,代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    WSADATA wsadata;
    SOCKET sockSrv;
    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        return -1;
    }

    sockSrv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockSrv < 0)
    {
        return -1;
    }

    return 0;
}

在这段代码中,我们同样使用了socket函数来创建Socket。

  1. 绑定地址和端口号

接下来,我们需要绑定本地地址和端口号。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    SOCKADDR_IN addrSrv;
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) < 0)
    {
        return -1;
    }

    ...
}

在这段代码中,我们定义了本地地址(包括端口号和IP地址),并使用bind函数将Socket和地址进行绑定。

  1. 监听连接请求

绑定完成后,我们需要使用listen函数监听连接请求。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    if (listen(sockSrv, 10) < 0)
    {
        return -1;
    }

    ...
}

在这段代码中,我们使用了listen函数来监听连接请求,参数10表示最大连接数。

  1. 接受连接请求

监听完成后,我们通过accept函数接收连接请求。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);
    SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);

    ...
}

在这段代码中,我们先定义了addrClient来存储客户端地址,然后使用accept函数接受连接请求,返回一个与客户端通信的Socket。

  1. 接收和发送数据

连接成功后,我们可以使用recv函数来接收客户端发送的数据,使用send函数来向客户端发送数据。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    char recvBuf[100];
    int len = recv(sockConn, recvBuf, 100, 0);

    char buf[] = "Hello Client!";
    send(sockConn, buf, strlen(buf), 0);

    ...
}

在这段代码中,我们使用recv函数接收客户端发送的数据,然后使用send函数发送一段字符串给客户端。

  1. 关闭Socket

最后,在完成服务端的所有操作后,我们需要使用closesocket函数来关闭所有的Socket。代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    ...

    closesocket(sockSrv);
    closesocket(sockConn);
    WSACleanup();

    return 0;
}

三、示例说明

以上是实现TCP Socket客户端和服务端的详细步骤,下面我将通过两个示例代码来展示具体实现方法。

示例一:通过TCP Socket实现简单的聊天室

在这个示例中,我们通过TCP Socket实现一个简单的聊天室。代码如下:

//Server
#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#include <iostream>

using namespace std;

int main()
{
    WSADATA wsadata;
    SOCKET sockSrv, sockConn;
    SOCKADDR_IN addrSrv, addrClient;

    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        return -1;
    }

    sockSrv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockSrv < 0)
    {
        return -1;
    }

    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) < 0)
    {
        return -1;
    }

    if (listen(sockSrv, 10) < 0)
    {
        return -1;
    }

    int len = sizeof(SOCKADDR);

    cout << "Server is listening..." << endl;

    sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
    cout << "A client connected!" << endl;

    while (1)
    {
        char recvBuf[100];
        int len = recv(sockConn, recvBuf, 100, 0);

        if (len <= 0)
        {
            break;
        }

        recvBuf[len] = '\0';
        cout << "Client: " << recvBuf << endl;

        char buf[100];
        cin >> buf;

        send(sockConn, buf, strlen(buf), 0);
    }

    closesocket(sockSrv);
    closesocket(sockConn);
    WSACleanup();

    return 0;
}


//Client
#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#include <iostream>

using namespace std;

int main()
{
    WSADATA wsadata;
    SOCKET sockClient;
    SOCKADDR_IN addrSrv;

    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        return -1;
    }

    sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockClient < 0)
    {
        return -1;
    }

    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) < 0)
    {
        return -1;
    }
    cout << "Connected to server!" << endl;

    while (1)
    {
        char buf[100];
        cin >> buf;

        send(sockClient, buf, strlen(buf), 0);

        char recvBuf[100];
        int len = recv(sockClient, recvBuf, 100, 0);
        recvBuf[len] = '\0';

        cout << "Server: " << recvBuf << endl;
    }

    closesocket(sockClient);
    WSACleanup();

    return 0;
}

在这个聊天室示例中,我们首先编写了一个服务端程序,用于监听连接请求。在客户端连接成功后,服务端会开始运行一个循环,等待客户端发送消息。当服务端接收到消息时,它会输出客户端发送的消息,并等待输入下一条消息发送给客户端。

客户端程序会首先连接到服务端,然后进入一个循环,等待用户输入消息。当用户输入一条消息时,客户端会将它发送给服务端,并等待服务端发送消息。客户端接收到服务端的消息后,会将该消息输出到屏幕上。

示例二:通过TCP Socket进行文件传输

在这个示例中,我们将使用TCP Socket实现简单的文件传输。将一个本地文件传输到远程机器上。该示例将演示文件的发送和接收过程。

服务端代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    WSADATA wsadata;
    SOCKET sockSrv, sockConn;
    SOCKADDR_IN addrSrv;

    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        return -1;
    }

    sockSrv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockSrv < 0)
    {
        return -1;
    }

    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) < 0)
    {
        return -1;
    }

    if (listen(sockSrv, 10) < 0)
    {
        return -1;
    }

    int len = sizeof(SOCKADDR);
    sockConn = accept(sockSrv, NULL, NULL);

    FILE* file = fopen("test.txt", "rb");
    char buf[1024];

    while (1)
    {
        int len = fread(buf, 1, 1024, file);

        if (len <= 0)
        {
            break;
        }

        send(sockConn, buf, len, 0);
    }

    fclose(file);

    closesocket(sockSrv);
    closesocket(sockConn);
    WSACleanup();

    return 0;
}

客户端代码如下:

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    WSADATA wsadata;
    SOCKET sockClient;
    SOCKADDR_IN addrSrv;

    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        return -1;
    }

    sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockClient < 0)
    {
        return -1;
    }

    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6000);
    addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) < 0)
    {
        return -1;
    }

    FILE* file = fopen("test_recv.txt", "wb");
    char buf[1024];

    while (1)
    {
        int len = recv(sockClient, buf, 1024, 0);

        if (len <= 0)
        {
            break;
        }

        fwrite(buf, 1, len, file);
    }

    fclose(file);

    closesocket(sockClient);
    WSACleanup();

    return 0;
}

本示例中,服务端首先通过文件流打开一个名为“test.txt”的本地文件,并每次读取1024字节的数据发送给客户端。客户端在接收到数据后,将接收到的数据写入到一个名为“test_recv.txt”的本地文件中。在完成数据传输后,服务端和客户端都会关闭连接和socket。

以上就是通过VC++实现TCP Socket客户端和服务端所需要遵循的流程及代码示例说明,希望对您有所帮助。

阅读剩余 90%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vc++实现的tcp socket客户端和服务端示例 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 原生js自定义右键菜单

    了解了您的需求,我针对“原生js自定义右键菜单”的完整攻略,提供如下讲解。 1. 添加右键菜单的基本思路 我们可以通过在DOM元素上绑定鼠标右击事件,再利用CSS样式和JavaScript代码控制菜单的显示和隐藏。 具体的实现步骤如下: 监听鼠标右击事件 创建一个div元素用于显示菜单,将其样式设置为隐藏 在监听函数中,获取右击位置的坐标,并将菜单显示在该位…

    other 2023年6月25日
    00
  • Java实现双链表的示例代码

    下面我将为您详细讲解Java实现双链表的示例代码的完整攻略。 什么是双链表 双链表是一种常见的数据结构,在链表中每个节点中都存储了前驱节点和后继节点的地址。与单链表相比,双链表能够更快速地进行双向遍历,但是需要更多的空间来存储节点的前驱和后继节点地址。 Java实现双链表的步骤 下面是实现双链表的步骤: 定义节点类,该节点类应该包含前驱节点和后继节点的引用。…

    other 2023年6月27日
    00
  • python基础之多态

    Python基础之多态 什么是多态 多态是一种对象编程的重要特性,可以让不同类的对象对同一消息作出不同的响应。这些不同的响应都是基于这些对象的类所定义的。 换句话说,多态是指通过相同的接口调用不同的类型对象所产生的不同结果。这就是所谓的“一个接口,多种实现”。 多态的实现方式 在Python中,实现多态有两种方式: 函数重写(方法重定义) 继承和多重继承 以…

    other 2023年6月26日
    00
  • asp无限分级(递归调用)

    ASP无限分级递归调用攻略 ASP无限分级递归调用指的是通过递归实现树形结构的无限分级展示。这种展示方式非常常见,如商品分类、菜单导航栏等。 步骤 第一步:建立数据库表 首先,我们需要创建一张数据库表来存储所有分类数据。一般来说,至少包含三个字段:id、name 和 parent_id。 其中,id 是分类的唯一标识符,name 是分类名称,parent_i…

    other 2023年6月27日
    00
  • C语言for语句用法详解

    C语言for语句用法详解 简介 在C语言中,for语句是用于循环执行一系列代码语句的一种结构化语句。通常情况下,for语句用于循环执行已知次数的操作。for语句的基本形式如下: for (initialization; condition; increment) { statement(s); } 其中,initialization表示循环的初始状态;con…

    other 2023年6月27日
    00
  • ts数组声明类型数组

    ts数组声明类型数组 在TypeScript中,我们通常会遇到需要定义类型的情况,尤其在处理数组时更是如此。为了确保代码的可靠性和可维护性,我们需要学会如何声明类型数组。本文将为大家介绍如何在TypeScript中声明类型数组。 声明类型数组的语法 在 TypeScript 中,我们可以通过 Array<类型> 或者 [类型] 的方式来声明一个类…

    其他 2023年3月28日
    00
  • css父元素选择器

    什么是CSS父元素选择器? CSS父元素选择器是一种CSS选择器,它可以选择某个元素的父元素。使用CSS父元素选择器可以方便地对父元素进行样式设置,而不必为每个子元素单独设置样式。 如何使用CSS父元素选择器? CSS父元素选择器使用“>”符号来选择某个元素的直接父元素。以下是一个使用CSS父元素选择器的示例: <div class="…

    other 2023年5月7日
    00
  • 安全框架Shiro和Spring Security比较

    @ConditionalOnExpression是Spring Boot中的一个条件注解,它的作用是根据SpEL表达式的结果来决定是否创建一个Bean。下面是使用@ConditionalOnExpression的完整攻略。 使用方法 在Spring Boot应用程序中,使用@ConditionalOnExpression注解来标记一个Bean。 @Confi…

    other 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部