Linux网络编程

ARP

情况一:我与小胖位于同一子网。我向小胖的ip地址发起arp请求,小胖收到回应,告诉我他的mac地址,然后我向该mac地址发送hello即可。
情况二:我与小胖不在同一子网。由于不在同一子网,我需要向我的网关发送arp请求,网关告诉我mac地址,然后我向告诉网关:“向小胖的ip发hello”。剩下的事情,我就不用管了,如果网络可达,那么小胖就会收到我发的hello。

判断主机大小端

#include <iostream>
using namespace std;
int main()
{
    union
    {
        short value;
        char s[2];
    } t;
    t.value = 0x0102;
    if (t.s[0] == 0x01)
        cout << "大端" << endl;
    else if (t.s[0] == 0x02)
        cout << "小端" << endl;
    return 0;
}

IP地址转换

#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
    char addr[] = "192.168.1.1";
    unsigned int num = 0;
    inet_pton(AF_INET, addr, &num);
    unsigned char *p = (unsigned char *)&num;
    printf("%d %d %d %d\n", *p, *(p + 1), *(p + 2), *(p + 3));
    char show[16] = {0};
    const char *res = inet_ntop(AF_INET, &num, show, sizeof(show));
    cout << res << endl;
    return 0;
}

例:server和client的通信
server

#include <stdio.h>
#include <arpa/inet.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <unistd.h>
using namespace std;
void show(sockaddr_in caddr)
{
    char cIP[16] = {0};
    inet_ntop(AF_INET, &caddr.sin_addr.s_addr, cIP, sizeof(cIP));
    unsigned short clientPort = ntohs(caddr.sin_port);
    cout << cIP << ":" << clientPort << endl;
    return;
}
int rcv(int opfd)
{
    char rcvbuf[1024] = {0};
    int len = read(opfd, rcvbuf, sizeof(rcvbuf));
    if (len == -1)
    {
        perror("read");
        exit(-1);
    }
    else if (len > 0)
        cout << rcvbuf << endl;
    else
    {
        cout << "client closed..." << endl;
        return 0;
    }
}
void sd(int opfd)
{
    char sdbuf[1024] = {0};
    cin >> sdbuf;
    write(opfd, sdbuf, strlen(sdbuf));
}
int main()
{
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (lfd == -1)
    {
        perror("socket");
        exit(-1);
    }
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    inet_pton(AF_INET, "172.24.24.44", (void *)&saddr.sin_addr.s_addr);
    //saddr.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0
    saddr.sin_port = htons(9999);
    int ret = bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret == -1)
    {
        perror("bind");
        exit(-1);
    }
    ret = listen(lfd, 8);
    if (ret == -1)
    {
        perror("litsen");
        exit(-1);
    }
    struct sockaddr_in caddr;
    socklen_t len = sizeof(caddr);
    int opfd = accept(lfd, (struct sockaddr *)&caddr, &len);
    if (opfd == -1)
    {
        perror("accept");
        exit(-1);
    }
    show(caddr);
    pid_t pid = fork();
    if (pid > 0)
        while (rcv(opfd));
    else if (pid == 0)
    {
        while (1)
            sd(opfd);
    }
    close(opfd);
    close(lfd);
    return 0;
}

client

#include <stdio.h>
#include <arpa/inet.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <unistd.h>
using namespace std;
void sd(int fd)
{
    char buf[1024] = {0};
    cin >> buf;
    write(fd, buf, sizeof(buf));
    return;
}
int rcv(int fd)
{
    char rcvbuf[1024] = {0};
    int len = read(fd, rcvbuf, sizeof(rcvbuf));
    if (len == -1)
    {
        perror("read");
        exit(-1);
    }
    else if (len > 0)
        cout << rcvbuf << endl;
    else
    {
        cout << "client closed..." << endl;
        return false;
    }
    return true;
}
int main()
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1)
    {
        perror("socket");
        exit(0);
    }
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    inet_pton(AF_INET, "172.24.24.44", &saddr.sin_addr.s_addr);
    saddr.sin_family = AF_INET;
    int res = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (res == -1)
    {
        perror("conn");
        exit(-1);
    }
    pid_t pid = fork();
    if (pid > 0)
    {
        while (1)
            sd(fd);
    }
    else if (pid == 0)
    {
        while (rcv(fd))
            ;
    }
    close(fd);
    return 0;
}

多进程实现并发服务器

#include <stdio.h>
#include <arpa/inet.h>
#include <iostream>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <cstring>
#include <wait.h>
using namespace std;
void recyclechild(int arg)
{
    while (1)
    {
        int ret = waitpid(-1, NULL, WNOHANG);
        if (ret == -1)
            break;
        else if (ret == 0)
            break;
        else
            cout << ret << "recycled" << endl;
    }
}
int main()
{
    struct sigaction act;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    act.sa_handler = recyclechild;
    sigaction(SIGCHLD, &act, NULL);
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (lfd == -1)
    {
        perror("link");
        exit(-1);
    }
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(9999);
    saddr.sin_addr.s_addr = INADDR_ANY;
    int res = bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (res == -1)
    {
        perror("bind");
        exit(-1);
    }
    res = listen(lfd, 128);
    if (res == -1)
    {
        perror("listen");
        exit(-1);
    }
    while (1)
    {
        struct sockaddr_in caddr;
        socklen_t len = sizeof(caddr);
        int cfd = accept(lfd, (struct sockaddr *)&caddr, &len);
        if (cfd == -1)
        {
            if (errno == EINTR)
                continue;
            perror("accept");
            exit(-1);
        }
        pid_t pid = fork();
        if (pid == 0)
        {
            char cIP[16];
            inet_ntop(AF_INET, &caddr.sin_addr.s_addr, cIP, sizeof(cIP));
            unsigned short cPort = ntohs(caddr.sin_port);
            cout << cIP << ':' << cPort << endl;
            char buf[1024] = {0};
            int len = 0;
            while (len = read(cfd, buf, sizeof(buf)) > 0)
            {
                cout << buf << endl;
                write(cfd, "recieved", strlen("recieved"));
            }
            if (len == 0)
                cout << "client " << cIP << ':' << cPort << " closed..." << endl;
            else
                perror("read");
            close(cfd);
            exit(0);
        }
        else if (pid == -1)
        {
            perror("fork");
            exit(-1);
        }
    }
    close(lfd);
    return 0;
}

select完成IO多路复用

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <cstring>
#include <string>
using namespace std;
int main()
{
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
    listen(lfd, 8);

    fd_set rdset, tmp;
    FD_ZERO(&rdset);
    FD_SET(lfd, &rdset);
    int maxfd = lfd;
    while (1)
    {
        tmp = rdset;
        int res = select(maxfd + 1, &tmp, NULL, NULL, NULL);
        if (res == -1)
        {
            perror("select");
            exit(-1);
        }
        else if (res == 0)
            continue;
        else
        {
            if (FD_ISSET(lfd, &tmp))
            {
                int cfd;
                struct sockaddr_in caddr;
                unsigned int len = sizeof(caddr);
                cfd = accept(lfd, (struct sockaddr *)&caddr, &len);
                FD_SET(cfd, &rdset);
                maxfd = max(maxfd, cfd);
            }
            for (int i = lfd + 1; i <= maxfd; ++i)
            {
                if (FD_ISSET(i, &tmp))
                {
                    char buf[1024] = {0};
                    int len = read(i, buf, sizeof(buf));
                    if (len == -1)
                    {
                        perror("read");
                        exit(-1);
                    }
                    else if (len == 0)
                    {
                        cout << "closed..." << endl;
                        close(i);
                        FD_CLR(i, &rdset);
                    }
                    else
                    {
                        cout << buf << endl;
                        write(i, "recieved!", strlen("recieved!") + 1);
                    }
                }
            }
        }
    }
    close(lfd);
    return 0;
}

epoll服务端

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <cstring>
#include <string>
#include <sys/epoll.h>
using namespace std;
int main()
{
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
    listen(lfd, 8);

    int epfd = epoll_create(1);

    struct epoll_event epev;
    epev.events = EPOLLIN;
    epev.data.fd = lfd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &epev);
    struct epoll_event epevs[1024];
    while (1)
    {
        int ret = epoll_wait(epfd, epevs, 1024, -1);
        if (ret == -1)
        {
            perror("epoll");
            exit(-1);
        }
        cout << ret << endl;
        for (int i = 0; i < ret; ++i)
        {
            int curfd = epevs[i].data.fd;
            if (epevs[i].data.fd == lfd)
            {
                int cfd;
                struct sockaddr_in caddr;
                unsigned int len = sizeof(caddr);
                cfd = accept(lfd, (struct sockaddr *)&caddr, &len);
                epev.events = EPOLLIN;
                epev.data.fd = cfd;
                epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &epev);
            }
            else
            {
                char buf[1024] = {0};
                int len = read(curfd, buf, sizeof(buf));
                if (len == -1)
                {
                    perror("read");
                    exit(-1);
                }
                else if (len == 0)
                {
                    cout << "closed..." << endl;
                    close(curfd);
                    epoll_ctl(epfd, EPOLL_CTL_DEL, curfd, NULL);
                }
                else
                {
                    cout << buf << endl;
                    write(curfd, "recieved!", strlen("recieved!") + 1);
                }
            }
        }
    }
    close(epfd);
    close(lfd);
    return 0;
}

udp通信server

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
int main()
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in addr;
    addr.sin_port = htons(9999);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    while (1)
    {
        char buf[1024] = {0};
        char ipbuf[16] = {0};
        struct sockaddr_in caddr;
        socklen_t len = sizeof(caddr);
        recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&caddr, &len);
        cout << inet_ntop(AF_INET, &caddr.sin_addr.s_addr, ipbuf, sizeof(ipbuf)) << ':' << caddr.sin_port << endl;
        cout << buf << endl;
        sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&caddr, len);
    }
    close(fd);
    return 0;
}

udp通信client

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
int main()
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in addr;
    addr.sin_port = htons(9999);
    addr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
    socklen_t len = sizeof(addr);
    //bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    int cnt = 0;
    while (1)
    {
        char buf[1024] = {0};
        sprintf(buf, "hello:%d\n", ++cnt);
        sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&addr, len);
        recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
        cout << buf << endl;
        sleep(1);
    }
    close(fd);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值