【发布时间】:2019-10-04 13:26:14
【问题描述】:
我的套接字编程客户端的connect() 方法存在问题。我不确定问题出在我的代码还是我的运行方法上。我在两个单独的终端窗口中运行它——一个用于服务器(我首先运行),命令为“./server 8080”,另一个用于客户端,命令为“./client 4 8080 hello”。当我运行我的代码时,服务器程序在printf("this prints\n") 行之后的while 循环中停止。我认为这意味着它正在等待客户端连接到它。客户端程序在调用connect() 时失败,并打印出我的错误消息“连接失败”。我的代码发布在下面。
服务器代码:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#define bufsize 1024
void eatZombies(int n){
wait3(NULL,WNOHANG,NULL); // Nom Nom
}
int main(int argc, char *argv[]){
int sock, length, msgsock, status;
struct sockaddr_in server;
pid_t id;
signal(SIGCHLD, &eatZombies);
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(atoi(argv[1])); // this time 1st arg is port#
if(bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Error binding the socket\n");
exit(0);
}
if(listen(server_fd, SOMAXCONN) < 0){
printf("Error listening for connections\n");
exit(0);
}
char buffer[1024] = {0};
char *hello = "Hello from server";
int addrlen = sizeof(server);
while(1){
printf("this prints\n");
int client_fd = accept(server_fd, (struct sockaddr *)&server, (socklen_t*)&addrlen);
printf("this doesnt\n");
if(client_fd < 0){
printf("Error accepting connection\n");
exit(0);
}
// the next call makes a new child process that will actually handle the client.
id = fork();
// when id == 0, this is the child and needs to do the work for the server.
// when if > 0, this is the parent, and it should just loop around,
// when id < 0, we had an error.
if(id > 0){
continue;
}
else if(id < 0){
printf("Error\n");
exit(0);
}
read(client_fd, buffer, 1024);
printf("%s\n", buffer);
write(client_fd, hello, strlen(hello), 0);
printf("Hello message sent\n");
exit(0);
}
return 0;
}
客户代码:
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define bufsize 1024
int main(argc, argv) int argc; char *argv[];{
int sock, rval;
struct hostent *host;
struct sockaddr_in server; // not a pointer
char buf[bufsize];
printf("%d\n", argc);
if(argc != 4){
printf("usage:\ntcpclient hostname port string\n\n");
return(-1);
}
// look up hostname (server) using DNS
if ((host = gethostbyname(argv[1])) == 0) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
return(-1);
}
// Set up fields for socket to point to host and port
bcopy(host->h_addr, &server.sin_addr, host->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
// Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
printf("Socket Creation Failed\n");
exit(0);
}
// connect (3-way handshake)
if(connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Connection Failed\n");
exit(0);
}
// Copy the arg into buf so we can send it to the server
strncpy(buf, argv[3], bufsize);
// Send sentence to server
send(sock, buf, strlen(buf), 0);
printf("Message sent\n");
// read response from server
rval = read(sock, buf, bufsize);
// print result to window
fprintf(stdout,"%s\n", buf);
close(sock);
}
【问题讨论】:
-
在错误情况下将
printf更改为perror。这将打印调用失败原因的错误文本。 -
查看“写入”调用。编译器抱怨 write 需要 3 个参数。您指的是“发送”吗?
-
代码在 Linux Mint 19 上构建/运行正常。您将什么参数传递给客户端和服务器。特别是,您是否使用“localhost”和相同的端口号?
-
@dbush 我个人更喜欢
printf("something failed with error %d, (%s)", errno, strerror(errno)),结合了自定义错误信息+错误源... -
我的意思是“发送”。谢谢你的帮助。下面的答案建议我使用不同的命令行参数来解决问题。
标签: c++ c sockets networking