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;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值