Я новичок в программировании сокетов. Я пытаюсь создать серверную / клиентскую программу для загрузки файла.
Во-первых, я запускаю какой-то шаг, который я обычно делаю в другой программе, для настройки подключения клиента к серверу из формы.
Далее, со стороны сервера, я пытаюсь ввести количество байтов, которые отправляются клиенту, чтобы установить размер буфера приема. Со стороны клиента я получаю число в виде строки. Я конвертирую его в тип long и устанавливаю размер буфера.
Затем со стороны клиента я ввожу имя файла, который нужно загрузить с сервера. Сервер получает имя и проверяет, существует оно или нет.
Последний шаг (я думаю, ПРОБЛЕМА ШАГА) сервер пытается открыть файл. если файл открыт, отправьте имя файла обратно клиенту. клиент проверяет имя файла, если оно совпадает с отправленным или нет.
======> моя проблема в том, что имя файла отправляется обратно клиенту: - со стороны сервера: я распечатываю его и проверяю. это верно. - С клиента: я печатаю буфер сразу после чтения с сервера. Это не правильно. иногда пустоиногда это случайное значение.
Я сделал точно так же, как и предыдущий шаг.
Server.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
perror("you have to input port");
exit(1);
}
// init sockfd
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("sockfd perror");
exit(1);
}
// sockopt
int opt = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
// init server
bzero(&serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
// bind port
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
char buffer[256];
// write buff size
int buffsize;
printf("Input recive buffsize in Byte: ");
scanf("%d", &buffsize);
if (buffsize <= 0)
{
perror("Buffer size must be > 0");
exit(1);
}
bzero(buffer, sizeof(buffer));
bcopy(to_string(buffsize).c_str(), buffer, sizeof(buffer));
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("fail to send buffer size");
exit(0);
}
//read file name
bzero(buffer, sizeof(buffer));
n = read(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
// open file:
char filename[strlen(buffer) + 1];
bcopy(buffer, filename, sizeof(filename));
FILE *pf;
unsigned long fsize;
pf = fopen(filename, "rb");
if (pf == NULL)
{
bzero(buffer, sizeof(buffer));
bcopy("File not found", buffer, sizeof(buffer));
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
printf("File not found!\n");
return 1;
}
else
{
printf("File %s is openned \n", filename);
fseek(pf, 0, SEEK_END);
fsize = ftell(pf);
rewind(pf);
printf("File has %ld bytes!\n", fsize);
}
// write OK response file name
bzero(buffer, sizeof(buffer));
bcopy(filename, buffer, sizeof(buffer));
printf("\n\n\n\n%s\n\n\n\n", buffer);
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
close(newsockfd);
close(sockfd);
return 0;
}
Client.cpp
#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 <netdb.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
if (argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
// init sockfd
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("sockfd error");
exit(1);
}
// init server
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(portno);
// connect
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR connecting");
exit(1);
}
// recive and set buffer size:
char tempBuff[10];
bzero(tempBuff, 10);
n = read(sockfd, tempBuff, sizeof(tempBuff));
if (n < 0)
{
perror("fail to recive buffer size");
exit(1);
}
char buffer[stol(string(tempBuff))];
printf("Connect succes, Buffer size is %ld Bytes\n", sizeof(buffer));
// input file:
printf("Input file name to download: ");
string filename;
cin >> filename;
// Send filename
bzero(buffer, sizeof(buffer));
bcopy(filename.c_str(), buffer, filename.length());
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
}
// read file name response
bzero(buffer, sizeof(buffer));
n = read(sockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR reading from socket");
}
printf("\n\n\n\n%s, %ld\n\n\n\n", buffer, strlen(buffer));
// if (strcmp(buffer, filename.c_str()) == 0)
// {
// printf("OK!\n");
// }
// else
// {
// perror("Wrong filename");
// printf("server msg: %s\n", buffer);
// exit(1);
// }
close(sockfd);
return 0;
}
КОД ВЫПОЛНЕНИЯ С СЛЕДУЮЩЕЙ КОМАНДОЙ:
Клиент: ./client [ip сервера] [порт]
Сервер: ./server [порт]
Мой результат:
Обновление 1: проблема исчезает, когда я удаляю следующие строки:
// write buff size
int buffsize;
printf("Input recive buffsize in Byte: ");
scanf("%d", &buffsize);
if (buffsize <= 0)
{
perror("Buffer size must be > 0");
exit(1);
}
в server.cpp и этистрока:
// recive and set buffer size:
bzero(tempBuff, sizeof(tempBuff));
n = read(sockfd, tempBuff, sizeof(tempBuff));
if (n < 0)
{
perror("fail to recive buffer size");
exit(1);
}
// char buffer[stol(string(tempBuff))];
на client.cpp