UDP客户端和服务器

news/2024/5/18 13:17:17 标签: udp, 服务器, 网络协议

UDP客户端,也就是首先主动发送数据的一方,也就是发起服务请求的一方。

UDP服务器,也就是首先等待接收数据,并对接收的数据进行处理,返回计算结果的一方,也就是提供服务的一方。

涉及的函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
int send(int s, const void *msg, size_t len, int flags);

 udp客户端测试

测试代码 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int client_socket;
    client_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("client_socket = %d",client_socket);

    struct sockaddr_in server_addr;
    server_addr.sin_port = htons(6600);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.5");
    char buf[100];
    snprintf(buf,sizeof(buf),"time=%d",time(NULL));

    DEBUG_INFO("server_addr %s:%d on socket %d\n",
                           inet_ntoa(server_addr.sin_addr),
                           htons(server_addr.sin_port),
                           client_socket);
    socklen_t addrlen = sizeof(server_addr);
    int send_len = sendto(client_socket,buf,strlen(buf),0,&server_addr,sizeof(server_addr));
    memset(buf,0,sizeof(buf));
    DEBUG_INFO("sendto %s:%d \n",
                           inet_ntoa(server_addr.sin_addr),
                           htons(server_addr.sin_port));
    int read_len = recvfrom(client_socket,buf,sizeof(buf),0,&server_addr,&addrlen);
    DEBUG_INFO("recvfrom %s:%d  -- %s\n",
                           inet_ntoa(server_addr.sin_addr),
                           htons(server_addr.sin_port),
                           buf);
    
    sleep(5);
    return 0;
}

UDP接收端(服务器)

执行代码:

  

实验解析 

 UDP客户端向192.168.0.5:6600 地址发送时间值,UDP接受端,也就是调试助手,返回一个字符串。然后UDP客户端等待5秒退出。这可以用来实现一个NTP服务器

UDP服务端 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>

// #define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int server_socket;
    int res = 0;
    int on = 1;
    server_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("server_socket = %d",server_socket);

    if(setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,&on,sizeof(on)) < 0){
        perror("setsockopt");
        exit(-1);
    }

    struct sockaddr_in server_addr;
    server_addr.sin_port = htons(6600);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.11");

    res = bind(server_socket,(const struct sockaddr *)&server_addr,sizeof(server_addr));
    if(res == -1){
        perror("bind");
        return -1;
    }
    int len = 0;
    char buf[100];
    socklen_t addrlen;
    struct sockaddr_in client_server;
    while(1){
        memset(buf,0,sizeof(buf));
        memcpy(&client_server,&server_addr,sizeof(client_server));
        addrlen = sizeof(client_server);
        recvfrom(server_socket,buf,sizeof(buf),0,&client_server,&addrlen);
        DEBUG_INFO("buf = %s",buf);
        DEBUG_INFO("recfrom %s:%d  -- %s\n",
                           inet_ntoa(client_server.sin_addr),
                           htons(client_server.sin_port),
                           buf);
        addrlen = sizeof(client_server);
        sendto(server_socket,buf,strlen(buf),0,&client_server,addrlen);
    }
    
    sleep(5);
    return 0;
}

修改客户端中的IP地址为192.168.0.11,也就是虚拟机的IP地址

 实验解析:

服务器等待接收数据。客户端向服务端发送数据,服务器端接收数据后,将数据原样返回。然后服务端继续等待接收数据。客户端发送完毕后等待接收,接收到数据后睡眠5秒退出程序。

使用connect的客户端 

虽然UDP是无连接的,但是connect函数依然有效,它高速操作系统,默认从哪里接收数据,默认向谁发送数据。这样就可以使用read,wirte、send、recv这四个没有指定地址的函数来收发数据了。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>

#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

int main(int argc, char *argv[])
{
    int client_socket;
    int res = 0;
    client_socket = socket(AF_INET,SOCK_DGRAM,0);
    DEBUG_INFO("client_socket = %d",client_socket);

    struct sockaddr_in remote_addr;
    remote_addr.sin_port = htons(6600);
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_addr.s_addr = inet_addr("192.168.0.11");
    char buf[100];
    snprintf(buf,sizeof(buf),"time=%d",time(NULL));

    DEBUG_INFO("remote_addr %s:%d on socket %d\n",
                           inet_ntoa(remote_addr.sin_addr),
                           htons(remote_addr.sin_port),
                           client_socket);
    
    res = connect(client_socket,&remote_addr,sizeof(remote_addr));
    int send_len = send(client_socket,buf,strlen(buf),0);
    memset(buf,0,sizeof(buf));
    int read_len = recv(client_socket,buf,sizeof(buf),0);

    DEBUG_INFO("recv %s:%d  -- %s\n",
                           inet_ntoa(remote_addr.sin_addr),
                           htons(remote_addr.sin_port),
                           buf);
    
    sleep(5);
    return 0;
}

 测试结果:

 

小结


http://www.niftyadmin.cn/n/1725374.html

相关文章

LOJ#6259. 「CodePlus 2017 12 月赛」白金元首与独舞(矩阵树)

传送门 题解&#xff1a; 把原来存在的边全部缩到父节点&#xff0c; 最后的图就变为了一个个根节点为’.’或者连向外部的点。 我们把外部的点看做根节点&#xff0c;就转化为了树形图计数问题。 #include <bits/stdc.h> using namespace std; typedef long long LL…

BZOJ4455: [Zjoi2016]小星星(容斥)

传送门 题解&#xff1a; 我们能用O(n2|S|)O(n2|S|)的时间统计出所有点都是颜色集合SS中的一个颜色的方案树。然后2n" role="presentation">2n2n枚举SS做容斥即可。 时间复杂度O(3nn2)" role="presentation">O(3nn2)O(3nn2)。 #include…

HDU4336:Card Collector(min-max 容斥)

传送门 题解&#xff1a; 利用min−maxmin−max期望公式&#xff1a; E[max{Xi}]∑S′∈S(−1)|S′1|min{Xi∈S′}E[max{Xi}]∑S′∈S(−1)|S′1|min{Xi∈S′}2n2n枚举即可。 #include <bits/stdc.h> using namespace std; typedef long long LL; typedef double LD;…

Atcoder AGC001E : BBQ Hard(DP)

传送门 题解&#xff1a; 将组合数看做网格图上的单增路径之后O(|X|2)O(|X|2)做DP即可。 #include <bits/stdc.h> using namespace std; typedef long long LL; const int RLEN1<<18|1; inline char nc() {static char ibuf[RLEN],*ib,*ob;(ibob) && (o…

Atcoder AGC014E:Blue and Red Tree (启发式合并)

传送门 题解&#xff1a; 考虑边分治的过程&#xff0c; 最后一定存在两条既在原树上出现&#xff0c;也在新树上出现的边。 我们一定是最后处理这条边&#xff0c;这样就可以合并这两个点变为子问题处理&#xff0c;直到最后只有一个点为止。 合并用启发式合并即可&#x…

Atcoder AGC012D:Colorful Balls

传送门 题解&#xff1a; 容易发现交换具有传递性。所以答案为每个联通块方案之积。 进一步发现只需要与每种颜色最小的连边&#xff0c;之后统计出每个联通块的方案数为&#xff1a; n!Πai!n!Πai!#include <bits/stdc.h> using namespace std; typedef long long …

Atcoder AGC012C:Tautonym Puzzle(倍增)

传送门 题解&#xff1a; 一开始想到比较简单的O(log2n)O(log2⁡n)的方法以为能过&#xff0c;看来我还是太Naive了。 lognlog⁡n的方法类似快速幂。 相当于求包含n1n1个含空子串的对称串的串。 发现aXaYaXaY比XYXY多一倍&#xff0c; aXYaaXYa多一个&#xff0c;&#xff0…

Atcoder ARC063E:Integers on a Tree(DP)

传送门 题解&#xff1a; 我们DP出每个点的取值范围和奇偶性&#xff0c;如果合法那么一定可以构造出一组方案。 原因是保证了相邻的点的取任意值都能构造出解。 #include <bits/stdc.h> using namespace std; typedef long long LL; const int RLEN1<<18|1; i…