c - exit() 调用上的段错误
问题描述
我正在编写一个程序来模拟服务器和客户端的一次性密码。客户端发送一个明文或密文文件和一个密钥文件。服务器侦听客户端进程,该进程发送包含方法(加密 (otp_enc) 或解密 (otp_dec) 和两个文件名(input_file_name 和 key_file_name)的缓冲区。程序打开文件并将明文或密文写入缓冲区并发送回打印输出的客户端。
用户在命令行调用:
otp_dec_d [port_number] & (server runs in background)
otp_dec plaintext_file_name key_file_name [port_number]
该程序运行完美,除了如果方法与端口号不匹配,我试图将退出状态设置为 2,就像这样......
otp_dec_d 56780 &
otp_enc_d 56781 &
otp_enc plaintext_file_name key_file_name 56780
我遇到了段错误。知道为什么吗?我在这行下面指出。程序的其余部分运行良好,空白输出被发送回客户端,就像打印此错误一样。(if(strcmp(argv[0], method) != 0) 是 if 语句)
//header files
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "otp.h"
void error(const char *msg) { perror(msg); exit(1); } // Error function used for reporting issues
/*
Name: server
-----------------
Description:
This function simulates a server
Reads buffer input from the client
Tokenizes string
Opens files for writing specified in arguments list
Calls appropriate function for encrypt/decrypt
Sends back an output file
Parameters:
argv[] list from stdin (ex: otp_dec_d or otp_enc_d [port_number])
*/
int server(char* argv[])
{
//printf("%s %s\n", argv[0], argv[1]); //for testing purposes
int listenSocketFD, establishedConnectionFD, portNumber, charsRead;
socklen_t sizeOfClientInfo;
char buffer[300];
struct sockaddr_in serverAddress, clientAddress;
pid_t spawnPid = -5; //garbage value
char method[100]; //array to hold method name (otp_enc,or otp_dec)
char input_file_name[100]; //array to hold input file name
char key_file_name[100]; //array to hold key file name
char output_file_name[300] = "output_file"; //array to hold output file name (output_file)
char input[70000]; //array to hold recv file contents
char output[70000]; //array to hold send file contents
char key[70000]; //array to hold key file contents
int port; //int value to hold argv[1]
// Set up the address struct for this process (the server)
memset((char *)&serverAddress, '\0', sizeof(serverAddress)); // Clear out the address struct
portNumber = atoi(argv[1]); // Get the port number, convert to an integer from a string
serverAddress.sin_family = AF_INET; // Create a network-capable socket
serverAddress.sin_port = htons(portNumber); // Store the port number
serverAddress.sin_addr.s_addr = INADDR_ANY; // Any address is allowed for connection to this process
// Set up the socket
listenSocketFD = socket(AF_INET, SOCK_STREAM, 0); // Create the socket
if (listenSocketFD < 0) error("ERROR opening socket");
// Enable the socket to begin listening
if (bind(listenSocketFD, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) // Connect socket to port
error("ERROR on binding");
listen(listenSocketFD, 5); // Flip the socket on - it can now receive up to 5 connections
while(1) {
// Accept a connection, blocking if one is not available until one connects
sizeOfClientInfo = sizeof(clientAddress); // Get the size of the address for the client that will connect
establishedConnectionFD = accept(listenSocketFD, (struct sockaddr *)&clientAddress, &sizeOfClientInfo); // Accept
if (establishedConnectionFD < 0) error("ERROR on accept");
spawnPid = fork();
switch(spawnPid) {
case -1:
perror("Hull Breach!\n");
exit(1);
break;
case 0:
// Get the message from the client and display it
memset(buffer, '\0', strlen(buffer));
charsRead = recv(establishedConnectionFD, buffer, strlen(buffer)-1, 0); // Read the client's message from the socket
if (charsRead < 0) error("ERROR reading from socket");
//printf("SERVER: I received this from the client: \"%s\"\n", buffer);
//tokenize input from client
char* token = strtok(buffer, "\n");
strcpy(method, token); //transfer current value to method array
token = strtok(NULL, "\n"); //reset token
strcpy(input_file_name, token); //transfer current value to input_file_name array
token = strtok(NULL, "\n"); //reset token
strcpy(key_file_name, token); //transfer current value to key_file_name array
//printf("%s %s %s %s\n", method, input_file_name, key_file_name); //for testing purposes
//printf("%d\n", port); //for testing purposes
strcat(method, "_d"); //add _d to end of method
if(strcmp(argv[0], method) != 0) {
fprintf(stderr, "Error: could not contact %s on %s", argv[0], argv[1]);
exit(2); //SEG_FAULT HERE!!!!!
}
else {
//open input and key files for reading
FILE* input_file = fopen(input_file_name, "r");
FILE* key_file = fopen(key_file_name, "r");
//transfer file contents to arrays
fgets(input, 70000, input_file);
fgets(key, 70000, key_file);
//close files
fclose(input_file);
fclose(key_file);
//remove trailing newlines from arrays
input[strcspn(input, "\n")] = '\0';
key[strcspn(key, "\n")] = '\0';
//printf("%s\n%s\n", input, key); //for testing purposes
//printf("%s\n", argv[0]);
//printf("%s\n", method); //for testing purposes
/* --------------------- Handle encrypt v. decrypt --------------------- */
//if argument 1 in argv array is encrypt
if(strcmp("otp_enc_d", method) == 0)
encrypt(input, output, key);
//else if argument 1 in argv array is decrypt
else if(strcmp("otp_dec_d", method) == 0)
decrypt(input, output, key);
/* ------------------- End handle encrypt v. decrypt ------------------- */
}
//printf("%s\n", output); //for testing purposes
//Open output file and write contents to it
FILE* output_file = fopen(output_file_name, "w+");
fprintf(output_file, "%s", output);
// Send a Success message back to the client
charsRead = send(establishedConnectionFD, output_file_name, strlen(output_file_name), 0); // Send success back
//printf("%d\n", charsRead);
if (charsRead < 0) error("ERROR writing to socket");
// Close the existing socket which is connected to the client
close(establishedConnectionFD);
establishedConnectionFD = -1;
exit(0);
break;
default: ;
}
close(establishedConnectionFD);
establishedConnectionFD = -1;
wait(NULL);
}
close(listenSocketFD); // Close the listening socket
return 0;
}
解决方案
推荐阅读
- python - Python Click:如何为全局上下文更改 `info_name` 的值
- python - 从 csv 文件中读取特定列
- swift - SwiftUI - 无法在 Firebase 的 observeSingleEvent 内分配变量。返回零
- nuget - 依赖项中的 Nuget 包冲突
- javascript - 解析(输入)为 JSON 字符串
- ruby-on-rails - 使用基于 API 密钥的身份验证时使用的正确标头是什么
- android - mvvm 使用 dagger2 和 ViewModelFactory,不理解默认注入
- cython - 如果有同名的属性,Cython 不能引用 cdef 类中的声明类型?
- docker - Docker BuildKit 是否被认为是稳定的/生产友好的?
- javascript - 在输入字段下方使用带有自定义消息的 javascript 进行电子邮件验证