클라이언트 프로그램에서 수정할 수있는 정수를 저장하는 TCP 서버 프로그램을 작성해야합니다. 은행 계좌와 비슷해야합니다. 한 가지를 제외하고는 모두 잘 작동합니다.sprintf/snprintf가 버퍼에 올바르게 쓰지 못했습니다.
클라이언트가 처음 서버에 연결하면 환영 메시지 (서버는 반복적이어야하므로 한 번에 하나의 클라이언트 만 처리해야합니다)가 대기합니다. 서버는 항상 환영 메시지의 처음 몇 글자 만 보냅니다. 다른 모든 메시지는 완전하고 올바르게 전송됩니다.
49 번째 줄에서 환영 메시지는 먼저 char 배열로 복사 된 다음 소켓에 기록됩니다. 첫 번째 1-5 자만 보내집니다 (새 클라이언트가 연결될 때마다 다름). char 배열에 메시지를 복사 한 다음 소켓에 쓰는 sprintf()를 사용하는 다른 곳에서는 모든것이 원하는대로 작동합니다. snprintf()를 사용해 보았지만 작동하지 않습니다. 내가 도대체 뭘 잘못하고있는 겁니까? : 나는 서버에 명령을 입력 시작할 수, 그 후
Connected!
Waiting for welcome message...
We
: D
그래서 이것은 클라이언트 측의 예를 출력 할 것이다. 그러나 전체 환영 메시지는 두 글자 뒤에 나옵니다. 그러나 위에서 말했듯이, 때로는 그것의 단 한 문자, 때로는 다섯 문자 : D. 어쨌든
, 여기에 (: D 내가하지 않도록해야 다른 오류 또는 물건이있는 경우, 말해 주시기 바랍니다) : 내 코드의클라이언트 :
#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>
#define BufferSize 99999
void error(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char msg[BufferSize], data[BufferSize];
if (argc < 3) error("usage: <hostname> <port>\n");
server = gethostbyname(argv[1]);
if (server == NULL) error("Host not found!");
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("socket() error");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) error("connect() error");
printf("Connected!\nWaiting for welcome message...\n");
memset(msg, 0, BufferSize);
n = read(sockfd, msg, BufferSize - 1);
if (n < 0) error("read() error");
printf("%s\n", msg);
memset(data, 0, BufferSize);
while (fgets(data, BufferSize, stdin) != NULL) {
data[strlen(data) - 1] = '\0'; //remove trailing newline char
n = write(sockfd, data, strlen(data) + 1);
if (n < 0) error("write() error");
if (strcmp(data, "exit") == 0) break;
memset(msg, 0, BufferSize);
n = read(sockfd, msg, BufferSize - 1);
if (n < 0) error("read() error");
if (n==0) error("Server shut down...");
printf("%s\n", msg);
memset(data, 0, BufferSize);
}
close(sockfd);
return 0;
}
서버 :
#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 <limits.h>
#define BufferSize 99999
#define ClientWaiting 100
void error(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, n, amount, balance, balOld;
socklen_t clilen;
char msg[BufferSize], data[BufferSize], *splitBuf[2];
struct sockaddr_in serv_addr, cli_addr;
balance = 0;
if (argc < 2) error("usage: <port>");
portno = atoi(argv[1]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("socket() error");
memset(&serv_addr, 0, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) error("bind() error");
listen(sockfd, ClientWaiting);
while (1) {
printf("Waiting for new client...\n");
clilen = sizeof (cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("accept() error");
printf("New connection accepted...\n");
memset(data, 0, BufferSize);
sprintf(data, "Welcome!\nPlease use the following commands:\n<put, get> <positive integer>\nBalance: %d€", balance);
n = write(newsockfd, data, strlen(msg) + 1);
if (n < 0) error("write() error");
while (1) {
splitBuf[0] = NULL;
splitBuf[1] = NULL;
memset(data, 0, BufferSize);
memset(msg, 0, BufferSize);
n = read(newsockfd, msg, BufferSize - 1);
if (n < 0) {
fprintf(stderr, "read() error\n");
break;
}
if (n == 0) {
printf("Client disconnected...\n");
break;
}
printf("Message received: %s\n", msg);
if (strcmp(msg, "exit") == 0) break;
splitBuf[0] = strtok(msg, " ");
splitBuf[1] = strtok(NULL, " ");
if (splitBuf[1] == NULL) {
strcpy(data, "Please use the following commands:\n<put, get> <positive integer>");
} else {
amount = atoi(splitBuf[1]);
if (amount <= 0) {
strcpy(data, "Please use the following commands:\n<put, get> <positive integer>");
} else if (strcmp(splitBuf[0], "put") == 0) {
balOld = balance;
balance += amount;
if (balance < balOld) {
balance = INT_MAX;
sprintf(data, "Warning! Overflow!\nBalance: %d€", balance);
} else {
sprintf(data, "Balance: %d€", balance);
}
printf("New balance: %d€\n", balance);
} else if (strcmp(splitBuf[0], "get") == 0) {
balOld = balance;
balance -= amount;
if (balance > balOld) {
balance = INT_MIN;
sprintf(data, "Warning! Underflow!\nBalance: %d€", balance);
} else {
sprintf(data, "Balance: %d€", balance);
}
printf("New balance: %d€\n", balance);
}
}
n = write(newsockfd, data, strlen(data) + 1);
if (n < 0) error("write() error");
}
close(newsockfd);
}
close(newsockfd);
close(sockfd);
return 0;
}
[snprintf (3)] (http://man7.org/linux/man-pages/man3/snprintf.3.html) (또는 Linux의 경우 'glibc', [asprintf (3) ] (http://man7.org/linux/man-pages/man3/asprintf.3.html)). 그것은 문서화 된대로 작동합니다. 종종 결과를 사용해야합니다. 'gcc -Wall -Wextra -g' (모든 경고와 디버그 정보)로 두 코드를 컴파일하십시오. 그리고 ** 디버거 **를 사용하십시오 (예 : 두 개의 터미널에서 클라이언트 디버깅 용, 하나는 서버 디버깅 용). 모든 함수를 실패에 대해 테스트하십시오 (실패시'perror' 사용). –
흠, 잘 snprintf와 나는 똑같은 문제가 : 그것은 환영 메시지와 함께 제대로 작동하지 않지만, 괜찮아요 내가 다른 메시지와 함께 똑같은 방식으로 문자 배열에 복사합니다. 그리고 크기가 고정 된 char 배열이므로 asprintf()는 실제로 적용되지 않습니다. 맞습니까? : D – user2336377
환영 메시지를 쓸 때,'data'의 내용을 쓰고 있지만'strlen (msg) + 1'을 사용하여 길이를 얻습니다 ... 틀린 것 같습니다. – Dmitri