我使用fork()在C套接字编程中并发了tcp文件传输客户端/服务器。该程序应该执行以下操作:客户端应连接到服务器并要求输入txt。它将与文件一起存储,服务器将查找并发送txt。文件发送到客户端,然后将其存储在本地。这是针对一个大学的项目的,我得到的反馈是我的服务器代码中的Use fork是不正确的,并且它不应该工作,但是我的程序可以正常工作吗?我对fork()的使用是否错误?另外,当我的客户端连接到服务器时,为什么它连接到随机端口而不是8888,如下所示。
服务器:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024
void send_file(FILE *fp, int sockfd){
int n;
char data[SIZE] = {0};
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) < 0) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
return;
}
int main(){
// ip address and port
char *ip = "127.0.0.1";
int port = 8888;
// variables and structures
int e;
int sockfd, new_sock;
struct sockaddr_in server_addr, new_addr;
socklen_t addr_size;
char buffer[SIZE];
pid_t childpid;
FILE *fp;
char *filepath;
// 1. creating the socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created.\n");
// 2. writing the data in the structure
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = port;
// 3. binding the ip address with the port
addr_size = sizeof(server_addr);
e = bind(sockfd, (struct sockaddr*)&server_addr, addr_size);
if (e < 0){
perror("[-]Error in bind");
exit(1);
}
printf("[+]Binding successfull.\n");
// 4. listening to the clients
e = listen(sockfd, 10);
if (e < 0) {
perror("[-]Error in listen");
exit(1);
}
printf("[+]Listening...\n");
// 5. accepting the client connection.
while (1){
addr_size = sizeof(new_addr);
new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size);
if (new_sock < 0){
perror("[-]Error in accpet");
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(new_addr.sin_addr), ntohs(new_addr.sin_port));
childpid = fork();
if (childpid == 0){
close(sockfd);
while(1){
recv(new_sock, buffer, SIZE, 0);
if (strcmp(buffer, "LIST") == 0){
// send the list of filenames.
bzero(buffer, SIZE);
strcpy(buffer, "data.txt\nhello.txt");
send(new_sock, buffer, SIZE, 0);
bzero(buffer, SIZE);
}
else if (strcmp(buffer, "QUIT") == 0){
// connection disconnected.
printf("Connection disconnected from %s:%d\n", inet_ntoa(new_addr.sin_addr), ntohs(new_addr.sin_port));
break;
}
else {
// received the filename, send the file data.
if (strcmp(buffer, "data.txt") == 0){
filepath = "server_files/data.txt";
fp = fopen(filepath, "r");
send_file(fp, new_sock);
}
else if (strcmp(buffer, "hello.txt") == 0) {
filepath = "server_files/hello.txt";
fp = fopen(filepath, "r");
send_file(fp, new_sock);
}
bzero(buffer, SIZE);
send(new_sock, "\0", 1, 0);
bzero(buffer, SIZE);
}
}
}
}
}
客户
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024
void remove_char(char *s, int c){
/* This function is used to remove a character from the character array. */
int j, n = strlen(s);
for (int i=j=0; i<n; i++)
if (s[i] != c){
s[j++] = s[i];
}
s[j] = '\0';
}
void write_file(char *filepath, int sockfd){
int n;
FILE *fp;
char buffer[SIZE];
fp = fopen(filepath, "w");
if (fp == NULL) {
perror("[-]Error in creating file");
exit(1);
}
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n == 1) {
break;
return;
}
fprintf(fp, "%s", buffer);
fflush(fp);
bzero(buffer, SIZE);
}
return;
}
int main(){
// ip address and port
char *ip = "127.0.0.1";
int port = 8888;
// variables and structures,
int e;
int sockfd;
struct sockaddr_in server_addr;
char buffer[SIZE];
char *filepath;
// 1. creating the socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
perror("[-]Error in socket");
exit(1);
}
printf("[+]Client socket created.\n");
// 2. writing the data in the structure
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = port;
// 3. connect to the server
e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(sockfd < 0){
perror("[-]Error in connect");
exit(1);
}
printf("[+]Connected to the server\n");
printf("\n");
printf("List of the commands.\n");
printf("LIST - list all the files.\n");
printf("LOAD - download the file.\n");
printf(" LOAD <path>\n");
printf("QUIT - disconnect from the server.\n");
while(1){
fflush(stdout);
printf("> ");
fgets(buffer, SIZE, stdin);
if (strlen(buffer) > 1){
char *token1 = strtok(buffer, " ");
char *token2 = strtok(NULL, " ");
remove_char(token1, '\n');
if (strcmp(token1, "LIST") == 0) {
// list all the file of the server.
send(sockfd, buffer, SIZE, 0);
recv(sockfd, buffer, SIZE, 0);
printf("%s\n", buffer);
}
else if (strcmp(token1, "LOAD") == 0) {
if (token2 == NULL) {
printf("[-]Specify the correct filename.\n");
} else {
// save the data of the file received from the server.
remove_char(token2, '\n');
send(sockfd, token2, SIZE, 0);
if (strcmp(token2, "data.txt") == 0){
filepath = "client_files/data.txt";
write_file(filepath, sockfd);
printf("[+]File saved.\n");
}
else if (strcmp(token2, "hello.txt") == 0) {
filepath = "client_files/hello.txt";
write_file(filepath, sockfd);
printf("[+]File saved.\n");
}
else {
printf("Incorrect path\n");
}
}
}
else if (strcmp(token1, "QUIT") == 0) {
// disconnect from the server.
printf("[+]Disconnected from the server.\n");
send(sockfd, token1, SIZE, 0);
break;
}
else {
printf("[-]Invalid command\n");
}
}
bzero(buffer, SIZE);
}
}
您有几个问题:
-Don't close sockfd, this will prevent further connections from being accepted on the server
-The socket should be closed on both ends in the quit case
-The fact that the client side uses a random port is fine. Nothing needs to be changed there