我正在尝试将包含字符串的文件从客户端发送到服务器,然后让服务器保存收到的结果。到目前为止,我已经设法将数据从客户端发送到服务器,但是当服务器将结果保存在文本文件中时,它包含无法读取的无效字符。
该文件的内容大约有10行零(如下图所示)(以红色突出显示),其间有随机字符:
POST /apikey=json&command={"Parameter" : "Value"}\00\00\00\00\00\00\00\00\00ð|\00\00\00\00|'^O\00\00ÿÿÿÿ
我做了一些研究,并尝试使用二进制模式:(fp = fopen(“testfile.txt”,“wb”);但这并没有解决它。
服务器
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
return 2;
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
{
char buf[1000];
ssize_t len;
len = recv(new_fd, buf, sizeof(buf) - 1, 0);
if (len > 0) {
buf[len] = '\0';
printf("buffer: %s len: %d\n\n", buf, (int)len);
/* save to file */
FILE *fp;
fp = fopen( "testfile.txt" , "wb" ); //b for binary
fwrite(buf, 1, sizeof buf, fp);
fclose(fp);
}
}
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, "I received your message\n", 23, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
客户
#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include <netdb.h> /* struct hostent, gethostbyname */
#include <unistd.h>
void error(const char *msg) { perror(msg); exit(0); }
int main(int argc,char *argv[])
{
/* first what are we going to send and where are we going to send it? */
int portno = 3490; /* 3490 or 8080 */
char *host = "192.168.1.65"; /* localhost: 127.0.0.1 or 192.168.1.65 */
char *message_fmt = "POST /apikey=%s&command=%s HTTP/1.0\n\n";
struct hostent *server;
struct sockaddr_in serv_addr;
int sockfd, bytes, sent, received, total;
char message[1024],response[4096];
//if (argc < 3) { puts("Parameters: <apikey> <command>"); exit(0); }
/* fill in the parameters */
sprintf(message,message_fmt,argv[1],argv[2]);
printf("Request:\n%s\n",message);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
/* lookup the ip address */
server = gethostbyname(host);
printf("ip address: %s\n\n", host);
if (server == NULL) error("ERROR, no such host");
/* fill in the structure */
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
/* connect the socket */
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
/* send the request */
/********************************* reading input data and converting into JSOn format ***********************/
FILE *file = stdin;
char a[50], b[50];
while(1 == fscanf(file," %[^,]",a) ) /* Read data until a comma is detected, */
{
fgetc( file ); // Ignore , character
fscanf(file," %[^,]",b); /* Read data until a comma is detected, */
fgetc( file ); // Ignore , character
printf("{\"%s\" : \"%s\"}\n",a,b); /* Display results into {"A":"B"} format */
}
///sprintf(message,message_fmt,a[0],b[0]);
//total = strlen(message);
//printf("sending message %d\n",total);
sprintf(a, message_fmt,"json","{\"Parameter\" : \"Value\"}\n");
//total = strlen(a); // this takes the value of 'a' eg: 1, 2, 3, 4, - 'a' will be 1,3 while b=2,4
total = strlen(message);
sent = 0;
do {
bytes = write(sockfd,a+sent,total-sent);
if (bytes < 0)
error("ERROR writing message to socket");
if (bytes == 0)
break;
sent+=bytes;
} while (sent < total); //while (sent < 0);
printf("Post request sent \n");
//receive the response
printf("Receiving response \n");
memset(response,0,sizeof(response));
total = sizeof(response)-1;
received = 0;
do {
bytes = read(sockfd,response-received,total-received);
if (bytes < 0)
error("ERROR reading response from socket");
if (bytes == 0)
break;
received+=bytes;
} while(received < total); //while (received < 0);
printf("Response received\n");
if (received == total)
error("ERROR storing complete response from socket");
/* close the socket */
close(sockfd);
/* process response */
printf("\nServer Response:\n%s\n\n",response);
return 0;
}
摘要
1-从客户端向服务器发送字符串(例如Hello World)
2-服务器读取字符串,将其保存到文本文件中
3-但是文本文件包含无效字符和零
答案 0 :(得分:1)
不要将'sizeof buf'字节写入文件 - 缓冲区可能没有完全填满数据。使用'len'值代替recv()调用返回的值。