Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >C语言编写的UDP客户端不接收数据包。

C语言编写的UDP客户端不接收数据包。
EN

Stack Overflow用户
提问于 2019-12-11 22:53:23
回答 1查看 97关注 0票数 0

我正在C上编写一个客户端服务器程序,我无法处理这个问题:客户端向服务器发送消息,他得到消息,一切正常,但是当服务器向客户端发送消息时,它不会捕获UDP数据包。服务器成功完成,而客户端一直在等待消息,但没有收到消息。这是密码。

udpClient.c:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdlib.h>

#define BUF_SIZE 1024
#define BAD_EXIT_STATUS 1

void throw(int code, char * message) {
    printf("%s\n", message);
    exit(code);
}

char * readline(FILE * input) {
    int size = 64;
    char * line = malloc(size * sizeof(char));
    char currentString[64];

    while (1) {
        fgets(currentString, sizeof(currentString), input);

        if (strstr(currentString, "\n")) {
            strcat(line, currentString);
            break;
        } else {
            size += 64;
            line = realloc(line, size * sizeof(char));
            strcat(line, currentString);
        }
    }
    return line;
}

typedef struct Args {
    char* IP;       // -a IP
    int port;       // -p port
} Args;

Args get_args(int argc, char **argv) {
    Args args;
    char * addr;
    char * port;
    if ((addr = getenv("L2ADDR"))) {
        args.IP = addr;
    } else {
        args.IP = "127.0.0.1";
    }
    if ((port = getenv("L2PORT"))) {
        args.port = atoi(port);
    } else {
        args.port = 1234;
    }

    int opt;
    while((opt = getopt(argc, argv, "a:p:vh")) != -1) {
        switch(opt) {
            case 'a':
                args.IP = optarg;
                break;
            case 'p':
                args.port = atoi(optarg);
                break;
            case 'v':
                printf("Lab2Server beta v.0.1.0\n");
                exit(0);
            case 'h':
                printf("You can use: \n"
                       "\t-a [string] -- Sets ip address;\n"
                       "\t-p [string] -- Sets port;\n"
                       "\t-v -- Shows a version.\n");
                exit(0);
            default:
                throw(BAD_EXIT_STATUS, "Use key -h to get some help.\n");
        }
    }

    return args;
}


int main(int argc, char **argv){
    Args args = get_args(argc, argv);
    
    char c;
    bool a = true;
    
    int sockfd;
    struct sockaddr_in serverAddr;
    
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        throw(BAD_EXIT_STATUS, "Socket creation failed");
    }
    
    
    memset(&serverAddr, 0, sizeof(serverAddr));

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(args.port);
    serverAddr.sin_addr.s_addr = inet_addr(args.IP);
    char buffer[BUF_SIZE];
        printf("[Client]: ");
        char *request = readline(stdin);
        int n;
        socklen_t len;
    
        sendto(sockfd, (const char *) request, strlen(request), 0, (const struct sockaddr*)&serverAddr, sizeof(serverAddr));
        printf("[+]Data Send: %s", buffer);
        n = recvfrom(sockfd, (char *) buffer, BUF_SIZE, 0, (struct sockaddr *) &serverAddr, &len);
        printf("[Server]: %s", buffer);
    close(sockfd);
    return 0;

}

udpServer.c:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <math.h>
#include "utils.h"

#define BUF_SIZE 1024
#define ERROR_N_IS_BIG 1
#define ERROR_T_LESS_THAN_F 2
#define ERROR_N_IS_0 3
#define ERROR_NOT_ENOUGH_NUMBERS 4


int ds_size;
double *ds;

char *createResponse(char *buffer) {
    return buffer;
}

int main(int argc, char **argv){
    
    Args args = get_args(argc, argv); //прием аргов
    FILE *output = fopen(args.logFile, "w+"); // запись логов
    
    int sockfd; //для сокета
    struct sockaddr_in serveraddr, cliaddr; //сокеты сервера и клиента
    bool a = true;
    
    //обработка ошибки создания сокета
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        throw(BAD_EXIT_STATUS, "Socket creation failed");
    }
    

    memset(&serveraddr, 0, sizeof(serveraddr)); //выделение памяти под СС
    memset(&cliaddr, 0, sizeof(cliaddr)); // память под СК
    
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(args.port);
    serveraddr.sin_addr.s_addr = inet_addr(args.IP);
    
    if (bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) {
        throw(BAD_EXIT_STATUS, "Bind failed");
    }
    
    if (args.isDaemon) {
        pid_t process_id = 0;

        process_id = fork();
        if (process_id < 0) {
            throw(BAD_EXIT_STATUS, "Fork failed!\n");
        }
        if (process_id > 0) {
            printf("Server started with pid %d\n", process_id);
            exit(0);
        }

        umask(0);
        chdir("/");
        if (setsid() < 0) {
            throw(BAD_EXIT_STATUS, "Error on setsid()");
        }

        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
    }
    int n;
    socklen_t len;
    char buffer[BUF_SIZE];
    n = recvfrom(sockfd, (char *)buffer, BUF_SIZE, MSG_WAITALL, (struct sockaddr*)& cliaddr, &len);
    printf("[+]Data Received: %s", buffer);
    char *hello = "Hello from server";
    sendto(sockfd, (const char *) hello, strlen(hello), 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr));
    printf("Hello message sent.\n");


    return 0;
    
}

我还使用下一个文件使程序使用键运行。

Utils.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "utils.h"

void throw(int code, char * message) {
    printf("%s\n", message);
    exit(code);
}

Args get_args(int argc, char **argv) {
    Args args;
    char * wait;
    char * addr;
    char * port;
    char * logfile;
    if ((wait = getenv("L2WAIT"))) {
        args.waitFor = atoi(wait);
    } else {
        args.waitFor = 0;
    }
    if ((addr = getenv("L2ADDR"))) {
        args.IP = addr;
    } else {
        args.IP = "127.0.0.1";
    }
    if ((port = getenv("L2PORT"))) {
        args.port = atoi(port);
    } else {
        args.port = 1234;
    }
    if ((logfile = getenv("L2LOGFILE"))) {
        args.logFile = logfile;
    } else {
        args.logFile = "/tmp/lab2.log";
    }
    args.isDaemon = false;

    int opt;
    while((opt = getopt(argc, argv, "w:dl:a:p:vh")) != -1) {
        switch(opt) {
            case 'w':
                args.waitFor = atoi(optarg);
                break;
            case 'd':
                args.isDaemon = true;
                break;
            case 'l':
                args.logFile = optarg;
                break;
            case 'a':
                args.IP = optarg;
                break;
            case 'p':
                args.port = atoi(optarg);
                break;
            case 'v':
                printf("Lab2Server beta v.0.1.0\n");
                exit(0);
            case 'h':
                printf("You can use: \n"
                   "\t-w [int] -- Sets the delay;\n"
                   "\t-d -- Starts as daemon;\n"
                   "\t-a [string] -- Sets ip address;\n"
                   "\t-p [string] -- Sets port;\n"
                   "\t-l [string] -- Sets log file;\n"
                   "\t-v -- Shows a version.\n");
                exit(0);
            default:
                throw(BAD_EXIT_STATUS, "Use key -h to get some help.\n");
        }
    }

    return args;
}

double random_double(double min, double max) {
    return (double)rand() / RAND_MAX * (max - min) + min;
}

void logMessage(FILE * output, struct sockaddr_in client_addr, char * message) {
    time_t t = time(NULL);
    char * ip = inet_ntoa(client_addr.sin_addr);
    struct tm tm = *localtime(&t);
    fprintf(output, "[%d-%02d-%02d %02d:%02d:%02d | %s]: %s", tm.tm_year + 1900, tm.tm_mon + 1,
            tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ip, message);
    fflush(output);
}

Utils.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <netinet/in.h>

#ifndef UTILS_H
#define UTILS_H

#define BAD_EXIT_STATUS 1

typedef struct Args {
    int waitFor;    // -w N
    bool isDaemon;  // -d
    char* logFile;  // -l path
    char* IP;       // -a IP
    int port;       // -p port
} Args;

Args get_args(int, char**);

void throw(int, char*);

double random_double(double, double);

void logMessage(FILE *, struct sockaddr_in, char *);

#endif

这些程序是使用Make文件编译的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.PHONY: build clean

udpServer: udpServer.o utils.o
    gcc -o udpServer udpServer.o utils.o -lm

udpClient: udpClient.o
    gcc -o udpClient udpClient.o

udpServer.o: udpServer.c
    gcc -c -o udpServer.o udpServer.c -lm

udpClient.o: udpClient.c
    gcc -c -o udpClient.o udpClient.c

utils.o: utils.c
    gcc -c -o utils.o utils.c

clean:
    rm -rf *.o

build:
    make udpServer
    make udpClient
    make clean

因此,当您完成文件时,您需要运行make build来编译一个程序,然后使用命令./udpServer -a 127.0.0.1 -p 1234运行服务器(在"-a“之后,您可以发布任何您想要的IP-addr,在"-p”之后,您可以发布您想要的任何端口),在一个新的窗口中,您可以使用命令./udpClient -a 127.0.0.1 -p 1234运行一个客户端(在"-a“之后,您可以发布您想要的任何IP-addr,在"-p”之后,您可以发布您想要的任何端口)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-12 01:35:05

在文件udpServer.c中,函数sendto()使用无效的cliaddr。为了得到正确的值,我们在调用len之前初始化recvfrom()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
socklen_t len = sizeof(struct sockaddr);
recvfrom(sockfd, (char *)buffer, BUF_SIZE, MSG_WAITALL, (struct sockaddr*)& cliaddr, &len);

recvfrom手册建议

参数addrlen是一个值结果参数,调用方应在调用之前将初始化为与src_addr关联的缓冲区大小,并在返回时进行修改以指示源地址的实际大小。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59299188

复制
相关文章
python中星号的意义(**字典,*列表或元组)
传递实参和定义形参(所谓实参就是调用函数时传入的参数,形参则是定义函数是定义的参数)的时候,你还可以使用两个特殊的语法:*、** 。 调用函数时使用* ,** test(*args)中 * 的作用:其实就是把序列 args 中的每个元素,当作位置参数传进去。比如上面这个代码,如果 args 等于 (1,2,3) ,那么这个代码就等价于 test(1, 2, 3) 。 test(**kwargs)中** 的作用:则是把字典 kwargs 变成关键字参数传递。比如上面这个代码,如果 kwargs 等于 {
用户1214487
2018/01/24
3.7K0
Python中的字典遍历
备忘一下python中的字典如何遍历,没有什么太多技术含量.仅供作为初学者的我参考.
技术小黑屋
2018/09/04
2.7K0
Python中如何遍历字典
今天在写一个判断列表中的元素是否与字典中的key值相等的时候,需要用到字典的遍历,经过查阅资料,知道怎么遍历字典的key值;
bear_fish
2018/09/20
1.6K0
Python中如何遍历字典
python中列表排序,字典排序,列表中的字典排序
key= lambda dict1:dict1[0] #dict1[0]表示按键,dict1[1]表示按值。
用户8346838
2021/03/10
9.1K0
Python - 从字典列表中删除字典
字典是python的一个非常常用的功能,用于根据用户需要在其中存储数据。另一个典型的过程涉及编辑或操作此数据。要成为一名高效且快速的程序员,您必须弄清楚如何从字典列表中删除字典。有许多技术可以从词典列表中删除字典,本文将介绍这些技术。
很酷的站长
2023/08/11
2650
Python - 从字典列表中删除字典
Python中的循环:遍历列表、元组、字典和字符串
想想现实生活中的情况。你是一位在森林里测量树木的野外生物学家。你选一棵树,测量它的直径和高度,把它们写在你的笔记本上,估计它的总体积。接下来,你再选一棵树,测量它的直径和高度,把它们写在你的笔记本上,估计它的总体积。然后,你再选一棵树,测量它的直径和高度,把它们写在你的笔记本上,估计它的总体积。
deephub
2021/04/16
12.1K0
在Python中,不用while和for循环遍历列表
s1=s.encode(encoding='utf-8').decode('unicode_escape')
用户2337871
2019/07/19
5.5K0
Python: 遍历字典
遍历字典 d = {'x': 1, 'y': 2, 'z': 3} 遍历keys for key in d: print key, y x z for key in d.iterkeys(): # d.iterkeys(): an iterator over the keys of d print key, y x z for key in d.keys(): # d.keys() -> ['y', 'x', 'z'] print key, y x z 遍历value
用户2183996
2018/06/28
1.1K0
Python遍历字典
前面我们简单介绍了Python字典和Python获取字典值。今天我们来聊聊如何遍历python字典。我们还是以car为例子。下面简单介绍三种方法来遍历字典。
生信交流平台
2020/08/06
7240
python中循环遍历for怎么用_python遍历字典的值
Python 会自动将dict_1视为字典,并允许你迭代其key键。然后,我们就可以使用索引运算符,来获取每个value值。
全栈程序员站长
2022/09/22
6K0
python中循环遍历for怎么用_python遍历字典的值
Python - 删除列表中的重复字典
Python 是一个非常广泛使用的平台,用于 Web 开发、数据科学、机器学习以及自动化执行不同的过程。我们可以将数据存储在python中,以不同的数据类型,例如列表,字典,数据集。python字典中的数据和信息可以根据我们的选择进行编辑和更改
很酷的站长
2023/08/11
3651
Python - 删除列表中的重复字典
python3-列表中存储字典
# Auther: Aaron Fan #示例1: #定义几个字典 alien_0 = {"color":"green", "points":5} alien_1 = {"color":"yellow", "points":10} alien_2 = {"color":"red", "points":15} #把字典存入到列表aliens中 aliens = [alien_0, alien_1, alien_2] #遍历这个列表 for alien in aliens:    print(alien
py3study
2020/01/06
1.4K0
python3-字典中存储列表
# Auther: Aaron Fan #示例1: #存储所点披萨的信息 pizza = {    '外皮':'厚的',    '配料列表':['香菇', '奶酪'], } #概述所点的比萨 print('您点了一道"%s-外皮"的比萨信息: ' % pizza['外皮']) for 配料 in pizza['配料列表']:    print("\t%s" % 配料) #示例2: 最喜欢的语言 = {    '张三':['python','ruby'],    '李四':['c'],    
py3study
2020/01/07
1.8K0
python实用技巧:在列表,字典,集合中快速筛选数据
python中,要对列表、字典、集合进行数据筛选,最简单的方式就是用遍历,逐一对比,将符合条件的元素保存。这种方式虽然简单,但不够简洁优雅,以下用实例说明其他实现方式。 本文示例代码均用python
章鱼喵
2018/06/27
5.7K0
python列表、元组、字典
列表是由一序列特定顺序排列的元素组成的。可以把字符串,数字,字典等都可以任何东西加入到列表中,列表中的元素之间没有任何关系。列表也是自带下标的,默认也还是从0开始。列表常用方括号表示,即:[],元素用逗号隔开。
py3study
2020/01/15
1.2K0
Python中的列表、元祖、字典的区别
定义 方法 列表 可以包含不同类型的对象,可以增减元素,可以跟其他的列表结合或者把一个列表拆分,用[]来定义的eg:aList=[123,'abc',4.56,['inner','list'],7-9j] 1.list(str):将str转换成list类型,str可以使字符串也可以是元组类型2.aList.append('test'):追加元素到列表中去3.del aList[1]:删除列表中下标为1的元素del aList:删除整个列表4.cmp(list1,list2):比较两个列表的大小5.len(
py3study
2020/01/09
2.8K0
Go 语言入门系列:列表与字典及其遍历
前面的文章主要介绍了 Go 容器的数组和切片的基本概念以及使用。本文将会介绍列表与字典在 Go 语言中相关的使用,以及几种常用容易的遍历及其使用。。
aoho求索
2021/08/06
3.4K0
python 字典、列表、json转换
#!/usr/bin/python3   import json      #python字典类型转换为json对象   data = {       'id' : 1,       'name' : 'test1',       'age' : '1'   }   data2 = [{       'id' : 1,       'name' : 'test1',       'age' : '1'   },{       'id' : 2,       'name' : 'test2',       '
一朵灼灼华
2022/08/05
1.4K0
python之列表、元组、字典
3 深拷贝和浅拷贝 1 浅拷贝: 当列表中存在有个列表时,其修改这个列表中列表的某一个元素时,其他被拷贝的列表中的对应元素也将被拷贝,其在拷贝这个列表中的列表时,拷贝的是这个内嵌列表的内存位置。
py3study
2020/01/14
2.8K0
点击加载更多

相似问题

遍历python中的字典列表

21

在python中遍历字典内的列表

665

如何遍历python字典列表

21

Python -遍历列表字典

21

在列表中遍历字典

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文