socket编程——c语言封装——c++封装(一对一对话)

点击免费下载文件

一、不封装

server.c
/*
    服务端程序,客户端成功连接后,会向本服务程序发送一个字符串,收到后需要回复,才能继续进行。
    双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
    注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{

    // 第1步:创建服务端的socket。
    int listenfd;
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        return -1;
    }

    // 第2步:把服务端用于通信的地址和端口绑定到socket上。
    struct sockaddr_in servaddr = {0};            // 服务端地址信息的数据结构。
    servaddr.sin_family = AF_INET;                // 协议族,在socket编程中只能是AF_INET。
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
    //servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 指定ip地址。
    servaddr.sin_port = htons(8080); // 指定通信端口。

    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
    {
        perror("bind");
        close(listenfd);
        return -1;
    }

    // 第3步:把socket设置为监听模式。
    if (listen(listenfd, 5) != 0)
    {
        perror("listen");
        close(listenfd);
        return -1;
    }

    // 第4步:接受客户端的连接。
    int clientfd;                             // 客户端的socket。
    int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小
    struct sockaddr_in clientaddr;            // 客户端的地址信息。
    clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&socklen);
    printf("客户端(%s)已连接。\n", inet_ntoa(clientaddr.sin_addr));

    // 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
    char buffer[1024] = {0};
    int iret;

    while (1)
    {
        if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) // 接收客户端的请求报文。
        {
            printf("iret=%d\n", iret);
            break;
        }
        else
        {
            printf("recv message from:%s\n", buffer);
            memset(buffer, '\0', sizeof(buffer));

            scanf("%s", buffer); //从控制台获取字符串

            if (strcmp(buffer, "exit") == 0)
                break;
            if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) // 向客户端发送响应结果。
            {
                perror("send");
                break;
            }
            memset(buffer, '\0', sizeof(buffer));
        }
    }

    // 第6步:关闭socket,释放资源。
    close(listenfd);
    close(clientfd);
}
client.c
/*
    客户端程序,连接服务器后,先向服务器发送一个 hello 消息,
    双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
    注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    // 第1步:创建客户端的socket。
    int sockfd;
    if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
        perror("socket");
        return -1;
    }

    struct sockaddr_in servaddr = {0};
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8080);             // 指定服务端的通信端口。
    servaddr.sin_addr.s_addr = inet_addr("xxx"); //根据自己的情况修改

    if (connect(sockfd, (struct sockaddr *)&servaddr, (socklen_t)(sizeof(servaddr))) != 0) // 向服务端发起连接清求。
    {
        perror("connect");
        close(sockfd);
        return -1;
    }

    // 第3步:与服务端通信,发送一个报文后等待回复,然后再发下一个报文。
    int iret;
    char buf[128] = "hello";
    send(sockfd, buf, strlen(buf), 0);
    while (1)
    {
        if ((iret = recv(sockfd, buf, sizeof(buf), 0)) <= 0) //接收服务端的回应报文。
        {
            printf("iret=%d\n", iret);
            break;
        }
        else
        {
            printf("received msg from[%s]:%s\n", inet_ntoa(servaddr.sin_addr), buf); //打印出连接的客户端的ip和接收到的消息
            memset(buf, '\0', sizeof(buf));

            scanf("%s", buf); //从控制台获取字符串

            if (strncmp(buf, "exit", 4) == 0)
                break;
            if ((iret = send(sockfd, buf, strlen(buf), 0)) <= 0) // 向服务端发送请求报文。
            {
                perror("send");
                break;
            }
            memset(buf, '\0', sizeof(buf));
        }
    }
    // 第4步:关闭socket,释放资源。
    close(sockfd);
    return 0;
}

二、c语言封装

封装头文件

client_server.h

#ifndef __CLIENT_SERVER_H
#define __CLIENT_SERVER_H
#include <arpa/inet.h>

int createsocket(int *fd);
int begconnect(int fd, const struct sockaddr *__addr);
int bind_listen(int listenfd, const struct sockaddr *__addr);
#endif

封装源程序

client_server.c

#include "client_server.h"
#include "stdio.h"
#include "unistd.h"

int createsocket(int *fd) //创建socket
{
    if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
        perror("socket");
        return -1;
    }
    return 0;
}
int begconnect(int fd, const struct sockaddr *__addr) //开始连接服务程序
{
    if (connect(fd, __addr, (socklen_t)(sizeof(*__addr))) != 0) // 向服务端发起连接清求。
    {
        perror("connect");
        close(fd);
        return -1;
    }
    return 0;
}
int bind_listen(int listenfd, const struct sockaddr *__addr) //服务端绑定ip和端口并开始监听
{
    if (bind(listenfd, __addr, sizeof(*__addr)) != 0)
    {
        perror("bind");
        close(listenfd);
        return -1;
    }

    // 第3步:把socket设置为监听模式。
    if (listen(listenfd, 5) != 0)
    {
        perror("listen");
        close(listenfd);
        return -1;
    }
}

客户端应用程序

 /*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
    注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "client_server.h"

int main(int argc, char *argv[])
{
    // 第1步:创建客户端的socket。
    int clientfd;
    createsocket(&clientfd);

    struct sockaddr_in servaddr = {0};
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8080); // 指定服务端的通信端口。
    servaddr.sin_addr.s_addr = inet_addr("xxxx");  //根据实际情况更改

    begconnect(clientfd, (struct sockaddr *)&servaddr);

    // 第3步:与服务端通信,发送一个报文后等待回复,然后再发下一个报文。
    int iret;
    char buf[128] = "hello";
    send(clientfd, buf, strlen(buf), 0);
    printf("fd=%d\n", clientfd);
    while (1)
    {
        if ((iret = recv(clientfd, buf, sizeof(buf), 0)) <= 0) // 接收服务端的回应报文。
        {
            printf("iret=%d\n", iret);
            break;
        }
        else
        {
            printf("received msg from[%s]:%s\n", inet_ntoa(servaddr.sin_addr), buf);
            memset(buf, '\0', sizeof(buf));

            scanf("%s", buf);

            if (strncmp(buf, "exit", 4) == 0)
                break;
            if ((iret = send(clientfd, buf, strlen(buf), 0)) <= 0) // 向服务端发送请求报文。
            {
                perror("send");
                break;
            }
            memset(buf, '\0', sizeof(buf));
        }
    }
    // 第4步:关闭socket,释放资源。
    close(clientfd);
    return 0;
}

服务端应用程序

 /*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
    注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "client_server.h"

int main(int argc, char *argv[])
{

    // 第1步:创建服务端的socket。
    int listenfd;
    createsocket(&listenfd);

    // 第2步:把服务端用于通信的地址和端口绑定到socket上。
    struct sockaddr_in servaddr = {0};            // 服务端地址信息的数据结构。
    servaddr.sin_family = AF_INET;                // 协议族,在socket编程中只能是AF_INET。
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
    //servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 指定ip地址。
    servaddr.sin_port = htons(8080); // 指定通信端口。

    bind_listen(listenfd, (const struct sockaddr *)&servaddr);

    // 第4步:接受客户端的连接。
    int clientfd;                             // 客户端的socket。
    int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小
    struct sockaddr_in clientaddr;            // 客户端的地址信息。
    clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&socklen);
    printf("客户端(%s)已连接。\n", inet_ntoa(clientaddr.sin_addr));

    // 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
    char buffer[1024] = {0};
    int iret;
    printf("fd=%d\n", clientfd);

    while (1)
    {
        if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) // 接收客户端的请求报文。
        {
            printf("iret=%d\n", iret);
            break;
        }
        else
        {
            printf("recv message from:%s\n", buffer);
            memset(buffer, '\0', sizeof(buffer));
            
            scanf("%s", buffer);
            
            if (strcmp(buffer, "exit") == 0)
                break;
            if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) // 向客户端发送响应结果。
            {
                perror("send");
                break;
            }
            memset(buffer, '\0', sizeof(buffer));
        }
    }

    // 第6步:关闭socket,释放资源。
    close(listenfd);
    close(clientfd);
}

三、c++封装

服务端封装头文件

#ifndef __SERVER_H
#define __SERVER_H

#include <arpa/inet.h>

class server
{
private:
    int fd;
    struct sockaddr_in addr;

public:
    int newclientfd;
    server(struct sockaddr_in *addr);
    int createsocket(void);
    int bind_listen(void);
    int client_accept(struct sockaddr_in *addr);
    int recvmsg(void *__buf, int len);
    int sendmsd(const void *__buf, int len);
    ~server();
};

#endif

服务端封装源文件

#include "server.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

server::server(struct sockaddr_in *addr) //构造函数
{
    this->addr = *addr;
    this->newclientfd = -1;
    this->fd = -1;
}
int server::createsocket(void) //创建socket
{
    if ((this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
        perror("socket");
        return -1;
    }
    return 0;
}

int server::bind_listen(void) //绑定端口开始监听
{
    if (bind(this->fd, (const sockaddr *)&this->addr, (socklen_t)sizeof(this->addr)) != 0)
    {
        perror("bind");
        close(this->fd);
        return -1;
    }

    if (listen(this->fd, 5) != 0)
    {
        perror("listen");
        close(this->fd);
        return -1;
    }
    return 0;
}
int server::client_accept(struct sockaddr_in *addr) //接受客户端的连接请求
{
    if (addr != nullptr)
    {
        int addrlen = sizeof(*addr);
        this->newclientfd = accept(this->fd, (struct sockaddr *)addr, (socklen_t *)&addrlen);
        if (this->newclientfd == -1)
        {
            perror("accept erro:");
            return -1;
        }
        else
            printf("客户端(%s)已连接。\n", inet_ntoa(addr->sin_addr));
    }
    return 0;
}
int server::recvmsg(void *__buf, int len) //接收消息
{
    int readnum;
    readnum = recv(this->newclientfd, __buf, len, 0);
    return readnum;
}
int server::sendmsd(const void *__buf, int len) //发送消息
{
    int sendnum;
    sendnum = send(this->newclientfd, (char *)__buf, len, 0);
    return sendnum;
}

server::~server() //析构函数,释放socket资源
{
    if (this->fd >= 0)
        close(this->fd);
    if (this->newclientfd >= 0)
        close(this->newclientfd);
}

服务端应用程序

 /*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
    注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include "server.h"
#include <cstring>
#include <iostream>
int main()
{
    struct sockaddr_in serveraddr = {0};  //sockaddr_in结构体
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(8080);

    server server(&serveraddr);     //创建server对象
    if (server.createsocket() == -1)  //创建socket
        return -1;
    if (server.bind_listen() == -1)  //绑定ip和端口并开始监听
        return -1;

    struct sockaddr_in clientaddr;  //创建要连接的客户端sockaddr_in结构体
    if (server.client_accept(&clientaddr) == -1)
        return -1;

    char buf[128] = "hello";    //发送接收数据缓冲区

    int iret;
    while (1)
    {
        if ((iret = server.recvmsg(buf, sizeof(buf))) <= 0) // 接收服务端的回应报文。
        {
            printf("iret=%d\n", iret);
            break;
        }
        else
        {
            std::cout << "received msg from " << inet_ntoa(clientaddr.sin_addr) << ":" << buf << std::endl;    //打印连接的客户端ip和收到的消息
            memset(buf, '\0', sizeof(buf));

            std::cin.getline(buf, sizeof(buf));  //从控制台获取字符串

            if (strncmp(buf, "exit", 4) == 0)
                break;
            if ((iret = server.sendmsd(buf, sizeof(buf))) <= 0) // 向服务端发送请求报文。
            {
                perror("send");
                break;
            }
            memset(buf, '\0', sizeof(buf));
        }
    }
    return 0;
}

客户端应用程序

 /*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
    注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include "client.h"
#include <cstring>
#include <iostream>
int main()
{
    struct sockaddr_in clientaddr;
    clientaddr.sin_family = AF_INET;
    clientaddr.sin_addr.s_addr = inet_addr("xxxx");
    clientaddr.sin_port = htons(xxx);

    client client(&clientaddr);
    client.createsocket();
    client.begconnect();

    char buf[128] = {0};
    int iret;

    client.sendmsd("hello", 5);
    while (1)
    {
        if ((iret = client.recvmsg(buf, sizeof(buf))) <= 0) // 接收服务端的回应报文。
        {
            printf("iret=%d\n", iret);
            break;
        }
        else
        {
            std::cout << "received msg from " << inet_ntoa(clientaddr.sin_addr) << ":" << buf << std::endl;
            memset(buf, '\0', sizeof(buf));

            std::cin.getline(buf, sizeof(buf));

            if (strncmp(buf, "exit", 4) == 0)
                break;
            if ((iret = client.sendmsd(buf, sizeof(buf))) <= 0) // 向服务端发送请求报文。
            {
                perror("send");
                break;
            }
            memset(buf, '\0', sizeof(buf));
        }
    }

    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要封装一个TCP类,您可以遵循以下步骤: 1. 首先,您需要包含必要的头文件,包括<sys/socket.h>,<netinet/in.h>,<arpa/inet.h>等。 2. 创建一个TCP类,该类应该包含必要的成员函数和变量,例如连接,发送和接收数据等。 3. 在类中,您需要定义一个套接字描述符来存储套接字,可以使用int类型的变量来表示。 4. 创建一个构造函数,该函数应该创建套接字并初始化地址结构体。您可以在构造函数中使用以下函数: - socket()函数创建套接字。 - memset()函数初始化地址结构体。 - htons()和htonl()函数转换网络字节序和主机字节序。 - bind()函数将套接字与本地地址绑定。 - listen()函数使套接字处于监听状态。 5. 创建一个连接函数,该函数应该将套接字连接到远程服务器,您可以在连接函数中使用以下函数: - connect()函数连接套接字到远程服务器。 6. 创建发送和接收数据的函数,这些函数应该使用套接字发送和接收数据。 7. 最后,创建一个析构函数,该函数应该关闭套接字并释放所有资源。 下面是一个简单的示例代码: ```c #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> class TCP { private: int sock; struct sockaddr_in address; public: TCP() { sock = socket(AF_INET, SOCK_STREAM, 0); memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = htons(0); bind(sock, (struct sockaddr *)&address, sizeof(address)); listen(sock, 1); } ~TCP() { close(sock); } void connectToServer(const char *ip, int port) { memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(ip); address.sin_port = htons(port); connect(sock, (struct sockaddr *)&address, sizeof(address)); } ssize_t send(const void *buf, size_t len, int flags) { return send(sock, buf, len, flags); } ssize_t recv(void *buf, size_t len, int flags) { return recv(sock, buf, len, flags); } }; ``` 请注意,上述代码仅为示例,您可能需要根据您的实际需求进行修改。 ### 回答2: 在 C 语言中,可以使用结构体和函数来封装一个 TCP 类。 首先,可以通过定义一个结构体来表示 TCP 类的私有数据和公有方法,结构体中可以包含套接字描述符等私有属性,以及用于初始化和发送/接收数据的公有方法。例如: ```c typedef struct TCP { int sockfd; // 其他私有属性 // 公有方法 void (*connect)(struct TCP *self, const char *ip, int port); void (*send)(struct TCP *self, const char *data, int length); void (*receive)(struct TCP *self, char *buffer, int length); void (*close)(struct TCP *self); } TCP; ``` 然后,可以定义相应的方法来实现这些公有方法。例如: ```c void connect(struct TCP *self, const char *ip, int port) { // 创建套接字并连接 self->sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_address; memset(&server_address, 0, sizeof(server_address)); server_address.sin_family = AF_INET; server_address.sin_port = htons(port); inet_pton(AF_INET, ip, &(server_address.sin_addr)); if (connect(self->sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) { perror("连接失败"); exit(1); } } void send(struct TCP *self, const char *data, int length) { // 发送数据 send(self->sockfd, data, length, 0); } void receive(struct TCP *self, char *buffer, int length) { // 接收数据 recv(self->sockfd, buffer, length, 0); } void close(struct TCP *self) { // 关闭套接字 close(self->sockfd); } ``` 最后,可以编写一个创建 TCP 对象的工厂方法。例如: ```c TCP *TCP_new() { TCP *tcp = malloc(sizeof(TCP)); // 初始化私有属性 // 绑定公有方法 tcp->connect = connect; tcp->send = send; tcp->receive = receive; tcp->close = close; return tcp; } ``` 使用时,可以先通过工厂方法创建一个 TCP 对象,然后调用公有方法进行连接、发送数据、接收数据等操作。例如: ```c TCP *tcp = TCP_new(); tcp->connect(tcp, "127.0.0.1", 8080); tcp->send(tcp, "Hello", 5); char buffer[256]; tcp->receive(tcp, buffer, sizeof(buffer)); printf("Received: %s\n", buffer); tcp->close(tcp); free(tcp); ``` 以上就是用 C 语言封装一个 TCP 类的简单实现。通过结构体和函数的组合,可以将相关的数据和方法封装在一起,提供了更好的代码复用性和可维护性。 ### 回答3: 在C语言中,封装一个TCP类可以通过以下步骤进行: 首先,定义一个结构体来表示TCP类,该结构体包含以下成员变量: - int sockfd:用于保存TCP套接字的文件描述符。 - char ip_addr[16]:用于保存服务器的IP地址。 - int port:用于保存服务器的端口号。 然后,定义以下函数来实现TCP类的各种操作: 1. 初始化TCP连接: - void tcp_init(TCP *tcp):用于初始化TCP连接,在该函数中创建套接字并设置服务器的IP地址和端口号。 2. 建立TCP连接: - int tcp_connect(TCP *tcp):用于与服务器建立TCP连接,在该函数中通过调用connect()函数来连接到服务器。 3. 发送数据: - int tcp_send(TCP *tcp, char *data, int len):用于向服务器发送数据,其中data是要发送的数据,len是数据的长度。该函数通过调用send()函数来发送数据。 4. 接收数据: - int tcp_recv(TCP *tcp, char *buf, int len):用于从服务器接收数据,其中buf是接收数据的缓冲区,len是缓冲区的长度。该函数通过调用recv()函数来接收数据。 5. 关闭TCP连接: - void tcp_close(TCP *tcp):用于关闭TCP连接,在该函数中通过调用close()函数来关闭套接字。 最后,在主函数中可以通过创建一个TCP类的对象,并调用相应的函数来实现TCP连接的建立、数据的发送和接收,以及连接的关闭。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值