C 发送和接收不一致
好了,伙计们,我已经连续工作了两天,搜索bug,寻找去年的解决方案和其他软件,但都找到了 我的问题是,我需要编写一个相当简单的服务器-客户机应用程序,在这个应用程序中,响应和回复都可以。我写了一些小程序来演示我的问题 在您抱怨send和recv不完整之前,要检查的内容不应小于0。我知道我得检查一下 h只是所有输入和静态变量的标题C 发送和接收不一致,c,sockets,tcp,C,Sockets,Tcp,好了,伙计们,我已经连续工作了两天,搜索bug,寻找去年的解决方案和其他软件,但都找到了 我的问题是,我需要编写一个相当简单的服务器-客户机应用程序,在这个应用程序中,响应和回复都可以。我写了一些小程序来演示我的问题 在您抱怨send和recv不完整之前,要检查的内容不应小于0。我知道我得检查一下 h只是所有输入和静态变量的标题 // guard block: #ifndef COMMON_H #define COMMON_H // default hostname and port: #de
// guard block:
#ifndef COMMON_H
#define COMMON_H
// default hostname and port:
#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT "1280"
#include <stdarg.h>
#include <ctype.h>
// IO, C standard library, POSIX API, data types:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
// Sockets, TCP, ... :
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <fcntl.h>
// Assertions, errors, signals:
#include <assert.h>
#include <errno.h>
#include <signal.h>
static struct addrinfo *ai = NULL; // stores address information
static int sockfd = -1; // socket file descriptor
static int connfd = -1; // connection file descriptor
void terminate(int sig);
void init_signal_handler(void);
void free_ressources(void);
void error(char* format, ...);
void terminate(int sig) {
error("Caught signal %d. Terminating...\n",sig);
}
void init_signal_handler(void) {
struct sigaction sa;
sa.sa_handler = terminate;
if (-1 == sigemptyset(&(sa.sa_mask))) {
error("sigemptyset()");
}
if (-1 == sigaction(SIGINT, &sa, NULL)) {
error("sigaction()");
}
if (-1 == sigaction(SIGTERM, &sa, NULL)) {
error("sigaction()");
}
}
void error(char *format, ...) {
va_list arg;
va_start (arg, format);
(void) vfprintf (stderr, format, arg);
va_end (arg);
free_ressources();
exit(EXIT_FAILURE);
}
void free_ressources(void) {
(void) printf("Freeing all ressources...\n");
if(sockfd != -1) close(sockfd);
if(connfd != -1) close(connfd);
freeaddrinfo(ai);
}
#endif // COMMON_H
来自客户端的输出
Sending message 0XF0F0
Recieved from Server 0
Sending message 0XF0F1
Recieved from Server 0
Sending message 0XF0F2
Recieved from Server 0
Sending message 0XF0F3
Recieved from Server 0
Sending message 0XF0F4
Recieved from Server 0
Sending message 0XF0F5
Recieved from Server 0
Sending message 0XF0F6
Recieved from Server 0
Sending message 0XF0F7
Recieved from Server 0
Sending message 0XF0F8
Recieved from Server 0
Sending message 0XF0F9
Recieved from Server 0
Freeing all ressources...
总之,我知道这可能是一个愚蠢而简单的问题,但为什么会是这样呢?为什么服务器在发送第一条消息时崩溃,而客户机却试图将其消息扔进空白处
感谢您提前给出答案,我真的需要解决这个问题。您有一些小问题和一些大问题: 小型:
- 您不会影响
提示中的
,但当ai_协议
不为提示
NULL时,
需要它getaddrinfo()
- 您使用
的返回作为文件描述符,但它是一个错误代码号。必须在客户机中通过connect()
或在服务器中通过socket()
使用文件描述符返回accept()
- 在服务器中使用
时使用了错误的文件描述符。您不应该在处理send()
SOCK\u流中连接的文件描述符上发送数据
返回一个列表,您应该对它进行迭代,但您假设总是有一个结果,但它们可以是零或多个getaddrinfo()
初始化后,您可以使用提示
调用未定义的行为,因为memset()
所以当您在sizeof(struct addrinfo)>sizeof(struct addrinfo*)
上写零时(全局…全局无处不在)ai
- 你无缘无故地使用global
- 您可以逐行声明多个变量
- 你无缘无故地使用global
- 您没有验证所有系统调用错误李>
- 你无缘无故地使用global
好的,谢谢你们。我非常渴望解决这个问题。感谢所有的回答,尤其是@Stargateur和@user3629249 好的,有两件事我需要弄清楚,感谢你们,我现在明白了
CC = /usr/bin/gcc
CFLAGS = -std=c99 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -g -c
SERVER = server
CLIENT = client
all: $(SERVER).c $(CLIENT).c clean compile compile2
compile: $(SERVER).c $(CLIENT).c
gcc $(CFLAGS) $(SERVER).c
gcc $(CFLAGS) $(CLIENT).c
compile2: $(SERVER).o $(CLIENT).o
gcc $(SERVER).o -o $(SERVER)
gcc $(CLIENT).o -o $(CLIENT)
clean: $(SERVER) $(SERVER).o $(CLIENT) $(CLIENT).o
rm $(SERVER) $(SERVER).o
rm $(CLIENT) $(CLIENT).o
客户
#include "common.h"
static char *port = DEFAULT_PORT;
static char *host = DEFAULT_HOST;
int main() {
int s;
struct addrinfo hints, *rp;
memset(&ai, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
s = getaddrinfo(host, port, &hints, &ai);
if(s != 0) error("Couldn't get address info...\n");
for (rp=ai; rp != NULL; rp=rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(sockfd == -1) continue;
if((connfd = connect(sockfd, rp->ai_addr, rp->ai_addrlen)) != -1) break;
close(sockfd);
}
if(rp == NULL) error("Couldn't connect...\n");
uint8_t msg = 0x00;
for(int i = 0; i < 10; ++i) {
msg=(uint8_t)((int)msg+1);
(void) fprintf(stdout, "Sending message %#X\n", msg);
send(sockfd, &msg, 1, MSG_CONFIRM);
recv(sockfd, &msg, 1, MSG_CONFIRM);
(void) fprintf(stdout, "Recieved from Server %#X\n", msg);
}
free_ressources();
}
来自/客户
./client
Sending message 0X1
Recieved from Server 0X2
Sending message 0X3
Recieved from Server 0X4
Sending message 0X5
Recieved from Server 0X6
Sending message 0X7
Recieved from Server 0X8
Sending message 0X9
Recieved from Server 0XA
Sending message 0XB
Recieved from Server 0XC
Sending message 0XD
Recieved from Server 0XE
Sending message 0XF
Recieved from Server 0X10
Sending message 0X11
Recieved from Server 0X12
Sending message 0X13
Recieved from Server 0X14
Freeing all ressources...
“但我到处都看到我应该使用袜子。”什么?“无处不在”在哪里?accept()返回的套接字是绑定到客户端的套接字,因此您应该在发送/接收调用中使用它。@Stargateur Sry编辑了它,现在它包含了头too@MartinJames谢谢你的回复,是的,我被这个名字感动了。您是对的,不要将代码放在头文件中。不要在头文件中放置变量。编译时,请始终启用警告,然后修复这些警告。(对于
gcc
,至少使用:-Wall-Wextra-Wconversion-pedantic-std=gnu11
)所有这些都是大错误。事实上,你称之为“小”的那些比你称之为“大”的几个要大,它们实际上只是时尚宣言。@EJP取决于你的观点,对我来说,这些大问题是这些小问题的原因;)显然这只是个玩笑。谢谢你的回答,我现在将尝试使用你的信息,希望能解决这个问题。由于服务器的连接部分是给定的,我只需要验证错误,所以我认为这应该是正确的,但我现在将测试它
// server and client
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_PASSIVE,
.ai_protocol = IPPROTO_TCP,
};
// server
if (send(connfd, &msg_s, 1, MSG_CONFIRM) == -1) {
// error
}
// client
if (recv(sockfd, &msg_r, 1, MSG_CONFIRM) == -1) {
// error
}
CC = /usr/bin/gcc
CFLAGS = -std=c99 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -g -c
SERVER = server
CLIENT = client
all: $(SERVER).c $(CLIENT).c clean compile compile2
compile: $(SERVER).c $(CLIENT).c
gcc $(CFLAGS) $(SERVER).c
gcc $(CFLAGS) $(CLIENT).c
compile2: $(SERVER).o $(CLIENT).o
gcc $(SERVER).o -o $(SERVER)
gcc $(CLIENT).o -o $(CLIENT)
clean: $(SERVER) $(SERVER).o $(CLIENT) $(CLIENT).o
rm $(SERVER) $(SERVER).o
rm $(CLIENT) $(CLIENT).o
#include "common.h"
static char *port = DEFAULT_PORT;
static char *host = DEFAULT_HOST;
int main() {
int s;
struct addrinfo hints, *rp;
memset(&ai, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
s = getaddrinfo(host, port, &hints, &ai);
if(s != 0) error("Couldn't get address info...\n");
for (rp=ai; rp != NULL; rp=rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(sockfd == -1) continue;
if((connfd = connect(sockfd, rp->ai_addr, rp->ai_addrlen)) != -1) break;
close(sockfd);
}
if(rp == NULL) error("Couldn't connect...\n");
uint8_t msg = 0x00;
for(int i = 0; i < 10; ++i) {
msg=(uint8_t)((int)msg+1);
(void) fprintf(stdout, "Sending message %#X\n", msg);
send(sockfd, &msg, 1, MSG_CONFIRM);
recv(sockfd, &msg, 1, MSG_CONFIRM);
(void) fprintf(stdout, "Recieved from Server %#X\n", msg);
}
free_ressources();
}
#include "common.h"
static char *port = DEFAULT_PORT;
uint16_t read_from_client();
int main() {
struct addrinfo hints;
memset(&ai, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = 0;
int res = getaddrinfo(NULL, port, &hints, &ai);
if(res != 0) error("Failed to get addr info: %s\n", gai_strerror(res));
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(sockfd == -1) error("Couldn't create a socket\n");
int val = 1;
res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
if(res == -1) error("Socket options couldn't be set\n");
res = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
if(res == -1) error("Socket binding failed\n");
res = listen(sockfd, 1);
if(res == -1) error("Listener setup failed\n");
connfd = accept(sockfd, NULL, NULL);
if(connfd == -1) error("Server Accept failed\n");
uint8_t msg = 0x00;
for(int i = 0; i < 10; ++i) {
recv(connfd, &msg, 1, MSG_CONFIRM);
(void) fprintf(stdout, "Recieved from Client %#X\n", msg);
msg = (uint8_t) ((int)msg + 1);
(void) fprintf(stdout, "Sending %#X\n", msg);
send(connfd, &msg, 1, MSG_CONFIRM);
}
free_ressources();
}
./server
Recieved from Client 0X1
Sending 0X2
Recieved from Client 0X3
Sending 0X4
Recieved from Client 0X5
Sending 0X6
Recieved from Client 0X7
Sending 0X8
Recieved from Client 0X9
Sending 0XA
Recieved from Client 0XB
Sending 0XC
Recieved from Client 0XD
Sending 0XE
Recieved from Client 0XF
Sending 0X10
Recieved from Client 0X11
Sending 0X12
Recieved from Client 0X13
Sending 0X14
Freeing all ressources...
./client
Sending message 0X1
Recieved from Server 0X2
Sending message 0X3
Recieved from Server 0X4
Sending message 0X5
Recieved from Server 0X6
Sending message 0X7
Recieved from Server 0X8
Sending message 0X9
Recieved from Server 0XA
Sending message 0XB
Recieved from Server 0XC
Sending message 0XD
Recieved from Server 0XE
Sending message 0XF
Recieved from Server 0X10
Sending message 0X11
Recieved from Server 0X12
Sending message 0X13
Recieved from Server 0X14
Freeing all ressources...