Selamat tinggal! Saya sedang menulis program klien-server di C. Saya tidak dapat menangani masalah ini: Klien mengirim pesan ke server, dia menerimanya dan semuanya baik-baik saja, tetapi ketika Server mengirim pesan ke Klien, pesan itu tidak tertangkap paket UDP. Server selesai dengan sukses, sementara Klien terus menunggu pesan dan tidak menerimanya. Ini kodenya.
udpKlien.c:
#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:
#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;
}
Saya juga menggunakan file berikutnya untuk membuat program berjalan dengan kunci
Utils.c
#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
#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
Program-program ini dikompilasi menggunakan Make-file:
.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
Jadi ketika Anda menyelesaikan file, Anda perlu menjalankan make build
untuk membuat program dikompilasi dan kemudian Anda menjalankan server dengan perintah ./udpServer -a 127.0.0.1 -p 1234
(setelah "-a" Anda dapat memposting alamat IP apa pun yang Anda inginkan dan setelah "-p" Anda memposting apa saja port yang Anda inginkan) dan di jendela baru Anda menjalankan Klien dengan perintah ./udpClient -a 127.0.0.1 -p 1234
(setelah "-a" Anda dapat memposting alamat IP apa pun yang Anda inginkan dan setelah "-p" Anda memposting port apa pun yang Anda inginkan)
Tolong, bantu saya mengatasi masalah ini.... Saya di sini untuk menjawab semua pertanyaan Anda tentang program saya. Terima kasih banyak atas bantuannya!
len
alih-alihsizeof(cliaddr)
dalam panggilansendto()
server. - person Barmar   schedule 12.12.2019recvfrom()
tidak mengisi buffer dengan nol, jadi Anda tidak dapat mencetakbuffer
dengan format%s
. - person Barmar   schedule 12.12.2019