【发布时间】:2021-08-23 03:16:00
【问题描述】:
我创建了一个 TCP 客户端/服务器并获得了测试脚本,但是,除了短消息之外,所有测试都失败了。简单地说,脚本发送客户端通过从文件重定向到服务器读取的任意消息。但是,对于脚本随机创建的文件,它表示接收/发送端的消息不匹配。任何帮助将不胜感激,下面是客户端和服务器代码。
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#define QUEUE_LENGTH 10
#define RECV_BUFFER_SIZE 2048
/* TODO: server()
* Open socket and wait for client to connect
* Print received message to stdout
* Return 0 on success, non-zero on failure
*/
int server(char *server_port) {
int sockfd, new_fd;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address
socklen_t sin_size;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
char buff[RECV_BUFFER_SIZE];
int numBytes;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my ip address
if ((rv = getaddrinfo(NULL, server_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;
}
freeaddrinfo(servinfo); // all done with this structure
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, QUEUE_LENGTH) == -1) {
perror("listen");
exit(1);
}
// printf("server: waiting for connections...\n");
while (1) {
sin_size = sizeof their_addr;
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
if (!fork()) { // child process
close(sockfd); // child does not need the listener
if ((numBytes = recv(new_fd, buff, RECV_BUFFER_SIZE -1, 0)) == -1) {
perror("recv");
exit(1);
}
buff[numBytes] = '\0';
printf("%s", buff);
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
/*
* main():
* Parse command-line arguments and call server function
*/
int main(int argc, char **argv) {
char *server_port;
if (argc != 2) {
fprintf(stderr, "Usage: ./server-c [server port]\n");
exit(EXIT_FAILURE);
}
server_port = argv[1];
return server(server_port);
}
// client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#define SEND_BUFFER_SIZE 2048
/* TODO: client()
* Open socket and send message from stdin.
* Return 0 on success, non-zero on failure
*/
int client(char *server_ip, char *server_port)
{
int sockfd;
int status;
struct addrinfo hints, *servinfo, *p;
char send_buff[SEND_BUFFER_SIZE];
int numbytes;
char s[INET6_ADDRSTRLEN];
// getaddrinfo
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(server_ip, server_port, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getadrrinfo: %s\n", gai_strerror(status));
return 1;
}
for (p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1)
{
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
freeaddrinfo(servinfo);
// reading from stdin into send_buff, then send
if((numbytes = read(0, send_buff, SEND_BUFFER_SIZE)) != -1) {
if (send(sockfd, send_buff, numbytes, 0) == -1) {
perror("send");
exit(1);
}
}
close(sockfd);
return 0;
}
/*
* main()
* Parse command-line arguments and call client function
*/
int main(int argc, char **argv)
{
char *server_ip;
char *server_port;
if (argc != 3)
{
fprintf(stderr, "Usage: ./client-c [server IP] [server port] < [message]\n");
exit(EXIT_FAILURE);
}
server_ip = argv[1];
server_port = argv[2];
return client(server_ip, server_port);
}
【问题讨论】:
-
题外话:释放后不能再使用
p,指针失效了!而是检查套接字。 -
你的标准输入
< [message]去哪里了?您希望如何发送此输入? -
这里没有任何内容表明“接收/发送方的消息不匹配”。如果您假设一次发送 == 一次接收,那么您的假设是错误的。
-
所以输入是通过文本文件,例如 ./client 127.0.0.1 55554