Linux下UDP实现的聊天

Serv.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    //创建套接字
    //int socket(int domain, int type, int protocol);
    //  domain: 地址域 AF_INET   IPV4
    //  type:  套接字类型
    //      SOCK_STREAM 流式套接字  tcp
    //      SOCK_DGRAM  数据报套接字    udp
    //  protocol:   协议类型
    //      IPPROTO_TCP 6   tcp协议
    //      IPPROTO_UDP 17  udp协议
    //  返回值:非负整数(套接字描述符) 失败:-1
    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) {
        perror("socket error");
        return -1;
    }
    //为套接字绑定地址
    //int bind(int sockfd, const struct sockaddr *addr,socklen_t ad
    //drlen);
    //  sockfd: 套接字描述符
    //  addr:  地址信息
    //  addrlen:地址信息长度
    //  返回值:成功:0, 失败:-1
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    //uint16_t htons(uint16_t hostshort);
    //将一个短整形(16位)数据从主机字节序转换位网络字节序
    addr.sin_port = htons(9000);
    //in_addr_t inet_addr(const char *cp);
    //  将点分十进制的字符串IP地址转换为网络字节序的地址
    //  INADDR_ANY INADDR_BROADCAST
    addr.sin_addr.s_addr = inet_addr("192.168.122.133");
    socklen_t len = sizeof(struct sockaddr_in);
    int ret = bind(sockfd, (struct sockaddr*)&addr, len);
    if (ret < 0) {
        perror("bind error");
        return -1;
    }
    while(1) {
        //接收
        //ssize_t recvfrom(int sockfd, void *buf, size_t len, 
        //int flags,struct sockaddr *src_addr, socklen_t *addrlen)
        //sockfd:   套接字描述符
        //buf:     要发送的数据
        //len:     要发送的数据长度:
        //flags:   发送标志,0-默认阻塞
        //          MSG_PEEK    接收数据后数据并不会从缓冲区删除
        //          场景:探测型获取数据
        //src_addr: 发送端的地址信息
        //addrlen:  地址信息长度
        //返回值:实际读取到的数据字节长度
        char buff[1024] = {0};
        struct sockaddr_in cli_addr;
        recvfrom(sockfd, buff, 1023, 0, 
                (struct sockaddr*)&cli_addr, &len);
        printf("client say:%s\n", buff);
        //发送
        memset(buff, 0x00, 1024);
        printf("server say:");
        fflush(stdout);
        scanf("%s", buff);
        //ssize_t sendto(int sockfd, const void *buf, size_t len, 
        //int flag,struct sockaddr *dest_addr, socklen_t addrlen);
        //  sockfd: 套接字描述符
        //  buf:   要发送的数据
        //  len:   要发送的数据长度
        //  flag:  默认0,阻塞发送
        //  dest_addr: 数据要发送到的对端地址信息
        //  addrlen:   地址信息长度
        //  返回值:实际发送的数据长度  失败:-1
        sendto(sockfd, buff, strlen(buff), 0, 
                (struct sockaddr*)&cli_addr, len);
    } 
    //关闭套接字
    close(sockfd);

    return 0;
}

Cli.cpp

#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
class UdpSocket
{
    private:
        int _sockfd;
    public:
        //创建套接字
        bool Socket()
        {
            _sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            if (_sockfd < 0) {
                perror("socket error");
                return false;
            }
            return true;
        }
        //绑定地址
        bool Bind(std::string &ip, uint16_t port)
        {
            sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(sockaddr_in);
            int ret = bind(_sockfd, (sockaddr*)&addr, len);
            if (ret < 0) {
                perror("bind error");
                return false;
            }
            return true;
        }
        //接收数据
        ssize_t Recv(std::string *buf, sockaddr_in *addr = NULL)
        {
            ssize_t rlen;
            socklen_t len = sizeof(sockaddr_in);
            char tmp[1024];
            sockaddr_in saddr;
            rlen = recvfrom(_sockfd, tmp, 1024, 0, 
                    (sockaddr*)&saddr, &len);
            if (rlen < 0) {
                return -1;
            }
            //assign 从一个字符串中拷贝指定长度的数据到string中
            buf->assign(tmp, rlen);
            if (addr) {
                memcpy(addr, &saddr, sizeof(sockaddr_in));
            }
            return rlen;
        }
        //发送数据
        ssize_t Send(std::string &buf, struct sockaddr_in *addr)
        {
            ssize_t slen;
            socklen_t len = sizeof(sockaddr_in);
            slen = sendto(_sockfd, buf.c_str(), buf.length(), 0,
                    (sockaddr*)addr, len);
            return slen;
        }
        //关闭套接字
        bool Close()
        {
            close(_sockfd);
        }
};

#define CHECK_RET(e) if((e) == false) { return false; }
int main()
{
    UdpSocket sock;
    CHECK_RET(sock.Socket());

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9000);
    addr.sin_addr.s_addr = inet_addr("192.168.122.133");
    while(1) {
        std::string buff;
        printf("client say: ");
        fflush(stdout);
        std::cin >> buff;
        sock.Send(buff, &addr);
        buff.clear();
        sock.Recv(&buff);
        printf("server say:%s\n", buff.c_str());
    }
    sock.Close();

    return 0;
}

注意更改一下ip地址和端口号。

猜你喜欢

转载自blog.csdn.net/q302989778/article/details/86561923