我在C中使用linux套接字设置了服务器和客户端。由于某种原因,我尝试发送的缓冲区的第一个字符丢失了(我给出的示例中的括号)。我认为这将是一个非常简单的调试周末,但到目前为止,我已经无处可去了。我认为发送前缓冲区是正确的,但发送后错误。我对套接字没有经验,这是我第一次尝试这种类型的东西,我真的很感激任何指针。该程序(可能更新)将用于接收我实习的公司的GPS跟踪坐标,这是我明天的最后一天,我真的很想让他们留下一些无用的东西。如果我没有提供足够的信息,那么请问!我试图在一个简单的c脚本中模拟我希望从客户端收到的输入。我相信这个问题可能是send()和recv()函数的第三个参数,但我真的不知道。在此先感谢,这是我的代码:
server.c
#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 <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define MYPORT 3490
#define BACKLOG 10
#define ONETRANSFER 1056
#define IDLENGTH 5
void sigchld_handler(int s) {
while(wait(NULL) > 0);
}
char* receiveFileName(int fd) {
char *fileName = malloc((IDLENGTH + 4) * sizeof(char));
int numBytes;
fileName[0] = 't';
fileName[1] = 'a';
fileName[2] = 'g';
if((numBytes = recv(fd, &fileName[3], IDLENGTH, 0)) == -1) {
/* Print to a log file here? Don't know the identity of the tag yet */
printf("Error in receiveFileName");
exit(1);
}
fileName[IDLENGTH + 3] = '\0';
return fileName;
}
char* receiveData(int fd, char* fileName, int dataSize) {
int dataReceived;
FILE *fp = fopen(fileName, "ab");//If this doesn't work try w, I think append is correct though
int i;
for(i = 0; i < dataSize; i++) {
char dataBuf[ONETRANSFER];
int remainingData = ONETRANSFER;
while(((dataReceived = recv(fd, &dataBuf, ONETRANSFER, 0)) >= 0) && (remainingData > 0)) {
if(dataReceived == 0){
printf("no data received\n");
break;
}
fwrite(dataBuf, sizeof(char), strlen(dataBuf), fp);
remainingData -= dataReceived;
// printf("Received %d bytes. We hope to receive %d more", dataReceived, remainingData); //For debug
printf("i = %d\n", i);
}
printf("exited\n");
}
fclose(fp);
//close(fd);
}
/* Sets up socket */
int setUpSocket() {
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error setting up socket()");
exit(1);
}
return sockfd;
}
/* Bind the socket */
void serverBind(int sockfd, struct sockaddr_in my_addr) {
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1){
perror("Error in bind()");
exit(1);
} else {
printf("Server-bind() is OK...\n");
}
}
int receiveDataSize(int fd) {
int dataSize, numBytes;
char buf[4];
if(numBytes = recv(fd, buf, 4, 0) == -1) {
/* Connection error, undecided as to how to respond atm */
}
buf[2] = '\0';
dataSize = strtol(buf, NULL, 10); /* 10 makes it decimal */
printf("The size is %d\n", dataSize);
return dataSize;
}
/* Listen and wait for the client */
void serverListen(int sockfd) {
if(listen(sockfd, BACKLOG) == -1) {
perror("Server-listen() error");
exit(1);
} else {
printf("Server-listen() is OK...Listening...\n");
}
}
int main(int argc, char* argv[]) {
int sockfd, newfd; /* listen on sock, new connection on new_fd */
struct sockaddr_in my_addr; /* my address info */
struct sockaddr_in their_addr; /* their adress info */
int sin_size;
struct sigaction sa;
int yes = 1; /* Need this as a pointer later */
sockfd = setUpSocket();
/* Set sock options */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("Error in setsockopt()");
exit(1);
}
/* host byte order */
my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
/* automatically fill with my IP */
my_addr.sin_addr.s_addr = INADDR_ANY;
/* zero the rest of the struct */
memset(&(my_addr.sin_zero), '\0', 8);
serverBind(sockfd, my_addr);
/* Set the server to listen for tags */
serverListen(sockfd);
/* clean all the dead processes */
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if(sigaction(SIGCHLD, &sa, NULL) == -1){
perror("Sigaction() error");
exit(1);
}
/* accept loop */
while(1) {
sin_size = sizeof(struct sockaddr_in);
if((newfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("Error in accept()");
continue;
}
/* If weird things start to happen include a case for fork unsuccessful */
/* This is the child process */
if(!fork()){
/* Maybe encorporate these two into one function? */
char* fileName = receiveFileName(newfd);
printf("The fileName is: %s", fileName);
int dataSize = receiveDataSize(newfd); /* return the value as a factor of 1056 e.g forg 2112 return 2*/
printf("The dataSize is: %d", dataSize);
receiveData(newfd, fileName, dataSize);
close(newfd);
exit(0);
} else {
/* This is the parent process, looks silly but needed to fork */
}
close(newfd);
}
return 0;
}
emulate.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORT 3490
#define SINGLETRANSFER 1056
#define IDLENGTH 5
#define ID 12345
int setUpSocket(void) {
int sockfd;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error setting up socket");
exit(1);
}
return sockfd;
}
void sendSize(char* buf, int fd) {
int bufLength = strlen(buf) + 1;
int dataSize = ((bufLength - 1) / SINGLETRANSFER) + 1; /* Number of "sections" sent */
printf("DataSize is %d", dataSize);
char sizeString[3]; //Here I am assuming that it wont be greater than 99 * 1056
sprintf(sizeString, "%d", dataSize);
if(send(fd, sizeString, 3, 0) == -1) {
perror("Error in sendLength");
exit(1);
}
}
void sendId(int fd, const char* id) {
int checkByte;
if((checkByte = send(fd, id, IDLENGTH, 0) == -1)) {
perror("Error in sending ID");
}
}
void sendData(char* data, int fd) {
int dataLength = strlen(data) + 1;
int totalBytesWritten = 0;
int numBytes;
printf("data[0] is: %c", data[0]);
while(totalBytesWritten != SINGLETRANSFER) {
//assert(totalBytesWritten < 1056);
if(numBytes = send(fd, data, dataLength - totalBytesWritten, 0) == -1) {
//printf("data left: %d\n", dataLength - totalBytesWritten);
perror("Error in sending in sendData()");
exit(1);
} else if (numBytes == 0) {
//printf("%d", totalBytesWritten);
break;
} else {
//printf("data left: %d\n", dataLength - totalBytesWritten);
//printf("numbytes: %d", numBytes);
totalBytesWritten += numBytes;
}
}
}
int main(int argc, char *argv[]) {
const char* id = "44444";
int sockfd, numbytes;
char* ip = "127.0.0.1";
/* I have no idea why but the first byte is being lost at some point, I have added a "NULL" byte at the beginning*/
char* data = "(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,01end"; /* 1056 bytes, it's a test file, doesn't need to be pretty :) */
struct hostent *he;
/* The address information of the connector */
struct sockaddr_in their_addr;
/* Get host info */
if((he = gethostbyname(ip)) == NULL) {
perror("getHostbyName");
exit(1);
}
/* set up the socket */
sockfd = setUpSocket();
/* Host byte order */
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
/* Set rest of struct to zero */
memset(&(their_addr.sin_zero), '\0', 8);
if(connect(sockfd, (struct sockaddr *) &their_addr, sizeof(struct sockaddr)) == -1) {
perror("Error in connect()");
exit(1);
} else {
printf("Connected ok\n");
}
/* Send the tag's ID */
sendId(sockfd, id);
printf("size of data is: %zu\n", strlen(data));
printf("The size of (int) data is: %d\n",(int) strlen(data));
/* Send the size of buffer (number of iterations of 1056) */
sendSize(data, sockfd);
/* Send the data */
sendData(data, sockfd);
return 0;
}
客户端一次发送1056个字节的数据,直到数据用完为止(我无法控制)
答案 0 :(得分:0)
交换数据大小时,发送三个字节的大小,但要求接收四个字节。假设这些调用实际上发送了三个字节,并且接收了四个字节,(这是无法保证的,你应该检查返回的值),然后是“receiveDataSize()&#39;将占用后面数据的第一个字节:(
答案 1 :(得分:0)
您提供的代码中存在大量错误,例如这也有问题:
while(((dataReceived = recv(fd, &dataBuf, ONETRANSFER, 0)) >= 0) && (remainingData > 0)) {
if(dataReceived == 0){
printf("no data received\n");
break;
}
fwrite(dataBuf, sizeof(char), strlen(dataBuf), fp);
remainingData -= dataReceived;
// printf("Received %d bytes. We hope to receive %d more", dataReceived, remainingData); //For debug
printf("i = %d\n", i);
}
应该是:
fwrite(dataBuf, sizeof(char), dataReceived , fp);