【发布时间】:2016-06-04 18:51:27
【问题描述】:
我正在尝试使用 UDP 编写客户端服务器程序,并等待并停止,但我还没有到那部分,我仍在试图弄清楚这两个进程(服务器和客户端) 通信,因为在我的客户端程序上,用户需要输入服务器名或IP地址,以及一个端口名,然后发送一个服务器应该计算的表达式。但是,我在互联网上挖了一些教程,在进行了相应的编码之后(或者我是这么认为的),我无法让客户端与服务器通信。下面是我的代码,如果是bind()、sendto()、recvfrom() 或socket(),或者所有这些,请告诉我我做错了什么。我看不出到底出了什么问题。我知道客户端不应该在无限循环上运行,但到目前为止我想让程序相互通信,然后我会完善我的代码。谢谢!
客户端代码:
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define FALSE 0
#define SERVERLEN 1024
int main(int argc, char **argv){
long portNum; // Since it's possible to input a value bigger
// than 65535 we'll be using long to
// avoid overflows
char expr[EXPR_SIZE];
char server[SERVERLEN];
int fd; // file descriptor for the connected socket
int buf[512];
struct hostent *h; // information of the host
unsigned int addrLen; // address length after getting the port number
struct sockaddr_in myaddr; // address of the client
struct sockaddr_in servaddr; // server's address
unsigned int exprLen;
socklen_t slen = sizeof(servaddr);
printf("Enter server name or IP address:");
scanf("%s",server);
printf("Enter port:");
scanf("%ld",&portNum);
if ((portNum < 0) || (portNum > 65535)) {
printf("Invalid port number. Terminating.");
return 0;
}
printf("Enter expression:");
scanf("%s",expr);
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
/*
// Discovering the port number the OS allocated
addrLen = sizeof(myaddr);
if(getsockname(fd, (struct sockaddr *)&myaddr, &addrLen) < 0){
perror("cannot getsockname");
return 0;
}
printf("local port number = %d\n", ntohs(myaddr.sin_port));
*/
memset((char*)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htonl(portNum);
exprLen = sizeof(expr);
while(TRUE){
printf("Sending message to %s port %ld\n",server, portNum);
if (sendto(fd, expr, strlen(expr), 0, (struct sockaddr *)&servaddr, slen) < 0) {
perror("cannot sendto()");
}
printf("Success\n");
}
return 0;
}
服务器端代码:
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define SERVERLEN 1024
int main(int argc, char **argv){
struct sockaddr_in myaddr; // address of the server
struct sockaddr_in claddr; // address of the client
char buf[BUFLEN];
int fd;
long recvlen;
socklen_t clientlen;
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
clientlen = sizeof(claddr);
while (TRUE) {
recvlen = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&claddr, &clientlen);
if (recvlen < 0) {
perror("cannot recvfrom()");
return 0;
}
printf("Received %ld bytes\n",recvlen);
buf[recvlen] = 0;
printf("Received message: \"%s\"\n",buf);
}
return 0;
}
服务端程序不输出任何东西,而客户端输出直到进程被中断:
Enter server name or IP address:127.0.0.1
Enter port:30
Enter expression:2+2
Sending message to 127.0.0.1 port 30
cannot sendto(): Can't assign requested address
我尝试将服务器名称更改为 localhost 和其他端口,但无济于事。
【问题讨论】:
-
"我无法让客户端与服务器通信。"。你能比那更具体一点吗?程序是否崩溃,是否不产生输出,是否产生错误的输出?等等。还包括您已经收集的任何调试结果。
-
你的客户端需要发送到服务器绑定的同一个端口。
-
对于客户端中的这一行:
scanf("%s",server);'%s' 格式说明符上没有输入字符修饰符的最大数量。因此,用户可能会超出输入缓冲区,从而导致未定义的行为,并可能导致段错误事件。建议:scanf("%1023s",server); -
客户端软件的编译会导致一些关于未使用参数、未使用变量、已设置但未使用的变量等的警告消息。修复所有这些警告的良好开端是替换当前的 main()带有
int main( void )的函数签名 -
在调用大多数系统函数时,例如
scanf(),始终检查返回值(不是参数值)以确保操作成功。
标签: c sockets unix client-server unix-socket