【发布时间】:2020-07-29 07:33:26
【问题描述】:
我是一名正在学习套接字编程的 UNI 学生,我的第一个任务是创建一个简单的客户端服务器模型,其中客户端发送一个字符串,服务器将其转换为全部大写并返回它。
我的代码没有出现任何错误,但是当我编译它时,服务器端在 for 循环的一次迭代后卡住了。
这是服务器端代码:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUF_LEN 48
//this function will convert string into upper case
int processString(char *input, char *output){
int len = strlen(input);
for (int i=0;i<len;i++){
output[i] = toupper(input[i]);
}
output[len]='\0';
return len;
}
int main(int argc,char *argv[]){
/* ----------------------------DECLARING VARIABLES---------------------------------- */
int ssd;
struct sockaddr_in server; //server info
struct sockaddr_in client; //client info
int client_len; // size of client
short echo_port; // the port number
int max_iterations; // usually runs forever but this will limit server
int byteInCount,byteOutCount,recieveCount,i;
char clientString[BUF_LEN];
char serverProcessedString[BUF_LEN];
int retCode;
/* ----------------------------END: DECLARING VARIABLES---------------------------------- */
/* ---------------------------CHECKING THE COMMAND LINE---------------------------- */
if (argc != 3)
{
fprintf(stderr,"incorrect usage! %s port Max_iterations\n",argv[0]);
exit(EXIT_FAILURE);
}
echo_port = atoi(argv[1]);
max_iterations = atoi(argv[2]);
/* ---------------------------END: CHECKING THE COMMAND LINE---------------------------- */
/* ----------------------------CREATE THE SOCKET CONNECTION---------------------------------- */
ssd = socket(PF_INET,SOCK_DGRAM,0); // refer to notes about meaning of each parameter
if (ssd <0){
perror("error in function socket()\n");
exit(EXIT_FAILURE);
}
server.sin_family=AF_INET; // ip protocol
server.sin_addr.s_addr=htonl(INADDR_ANY);
server.sin_port= htonl(echo_port); // port to serve on
retCode = bind(ssd,(struct sockaddr *)&server,sizeof(server)); // ask tut about bind() function
if (retCode <0)
{
perror("error in function bind()\n");
exit(EXIT_FAILURE);
}
/* ----------------------------END: CREATE THE SOCKET CONNECTION---------------------------------- */
/* ---------------------------- START THE SERVER---------------------------------- */
for (int i=0;i<max_iterations;i++){
fprintf(stderr,"Iteration %d of %d. Waiting for client...\n",i+1, max_iterations);
client_len = sizeof(client);
byteInCount = recvfrom(ssd,clientString,BUF_LEN,0,(struct sockaddr *)&client,(socklen_t *)&client_len);
if (byteInCount <0)
{
perror("error in function revfrom()\n");
exit(EXIT_FAILURE);
}
else{
fprintf(stderr,"revfrom() is all g\n");
}
fprintf(stderr,"Reversed string is %d bytes long\n", recieveCount);
fprintf(stderr,"Reversed string is \"%s\"\n",serverProcessedString);
byteOutCount = sendto(ssd,serverProcessedString,recieveCount+1,0,(struct sockaddr *)&client,sizeof(client));
if (byteOutCount <0){
perror("error in function sendto()\n");
exit(EXIT_FAILURE);
}
fprintf(stderr,"client request worked, reply has been sent\n");
}
close(ssd);
fprintf(stderr,"server has shutdown!\n");
return 0;
}
这是客户端代码:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUF_LEN 48
int main(int argc,char *argv[]){
int csd;
struct sockaddr_in server;
struct hostent *server_host;
int serverLength;
int stringSize;
short serverPort;
int byteInCount,byteOutCount;
char clientString[BUF_LEN];
char serverProcessedString[BUF_LEN];
if (argc != 4){
fprintf(stderr,"usage: %s server port send_string \n",argv[0]);
exit(EXIT_FAILURE);
}
server_host =gethostbyname(argv[1]);
if (server_host== NULL){
herror("error in function gethostbyname()\n"); // ask tut- this function is no longer used( getaddrinfo)
exit(EXIT_FAILURE);
}
serverPort= atoi(argv[2]);
strcpy(clientString,argv[3]);
csd = socket(PF_INET,SOCK_DGRAM,0);
if(csd <0)
{
perror("error in function socket()");
exit(EXIT_FAILURE);
}
server.sin_family= AF_INET;
memcpy(&server.sin_addr.s_addr,server_host->h_addr_list[0],server_host->h_length); // ask tut about this function
server.sin_port=htons(serverPort); // difference between htons and htonl???
stringSize=strlen(clientString)+1;
byteOutCount= sendto(csd,clientString,stringSize,0,(struct sockaddr *)&server,sizeof(server));
if (byteOutCount <0){
perror("error in function sendto()\n");
exit(EXIT_FAILURE);
}
fprintf(stderr,"You have sent \"%s\"\n",clientString);
fprintf(stderr,"Have reached recvfrom(), should now block until message receipt\n");
//get the response from server
serverLength = sizeof(server);
byteInCount = recvfrom(csd,serverProcessedString,BUF_LEN,0,(struct sockaddr *)&server,(socklen_t)&serverLength);
if (byteInCount <0){
perror("error in function recvfrom()\n");
exit(EXIT_FAILURE);
}
fprintf(stderr,"the server has responded with: : \"%s\"\n",serverProcessedString);
close(csd);
return 0;
}
我在 Ubuntu 虚拟机上编译这个: 1号航站楼
cc UDP_client.c -o send
./send 192.168.0.1 9999 hello
(上面的ip地址是通过ifconfig命令获取的)
2号航站楼
cc UDP_server.c -o rec
./rec 9999 10
我目前的输出:
2号航站楼
“第 1 次迭代,共 10 次。等待客户端”
1 号航站楼:
“你已经打招呼了”
“已经到达recvfrom(),现在应该阻塞直到收到消息”
我的循环似乎有问题? 任何帮助将不胜感激。
编辑:修复下面 cmets 中的错误后,在客户端我收到 recvfrom 函数中的错误:错误说,错误地址?
【问题讨论】:
-
一个问题:
server.sin_port= htonl(echo_port);。端口号是 16 位而不是 32 位。所以应该使用htons而不是htonl。 -
@kaylum 谢谢你,它解决了这个问题,请你看看我编辑的帖子
-
为什么
(socklen_t *)&client_len中有演员表?您的client_len变量应该已经是socklen_t而不是int。(socklen_t)&serverLength有同样的问题serverLength需要成为socklen_t变量。