我在Linux套接字编程上遇到了问题,我无法理解这种情况。
它是一个简单的echo服务器 - 客户端程序对。
这是我编程的:
这是echoClient。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define RCV_BUF_SIZE 512 //receive buffer size
int main(int argc, char *argv[])
{
int sock; //socket
struct sockaddr_in echoServAddr;//server socket address struct
unsigned short echoServPort; //server port
char *servIP; //server address
char *echoString; //sending msg
char echoBuffer[RCV_BUF_SIZE]; //receive buffer
unsigned int echoStringLen = 0; //msg length
int bytesRcvd, totalBytesRcvd; //received bytes, total bytes received
if((argc < 2) || (argc > 3)) //if there are no right arguements, throw error and exit program
{
printf("Usage : %s <Server IP> [<Echo Port>]\n", argv[0]);
exit(1);
}
servIP = argv[1];
if(argc == 3)//user defined exact port
{
echoServPort = atoi(argv[2]);
}
else//user didnt defined, use well-known port
{
echoServPort = 7;
}
if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)//if socket creation failed
{
printf("socket() failed\n");
exit(1);
}
memset(&echoServAddr, 0, sizeof(echoServAddr));//memory reset
echoServAddr.sin_family = AF_INET; //setting server's address
echoServAddr.sin_addr.s_addr = inet_addr(servIP);
echoServAddr.sin_port = htons(echoServPort);
if(connect(sock, (struct sockaddr*)&echoServAddr, sizeof(echoServAddr)) < 0)//connect try, -1 if failed
{
printf("connect() failed\n");
perror("error is : ");
exit(1);
}
printf("to exit, type \"/exit\"\n");
while(1)
{
printf("insert echo word : ");
echoString = gets();
echoStringLen = strlen(echoString);
if(echoStringLen > 512)//msg's length
{
printf("echo word is too long! (must be shorter than 512)\n");
echoStringLen = 0;
continue;
}
if(!strcmp(echoString, "\/exit"))
{
if(send(sock, echoString, echoStringLen, 0) != echoStringLen)//send to server, if sended bytes are smaller than string length
{
printf("sending close socket failed\n");
exit(1);
}
printf("clossing socket...\n");
break;
}
if(send(sock, echoString, echoStringLen, 0) != echoStringLen)//send to server, if sended bytes are smaller than string length
{
printf("send() failed\n");
exit(1);
}
totalBytesRcvd = 0;
while(totalBytesRcvd < echoStringLen)//while received bytes are shorter than msg's length
{
if((bytesRcvd = recv(sock, echoBuffer, RCV_BUF_SIZE-1, 0)) <= 0)//-1 for null char
{
printf("recv() failed");
exit(1);
}
totalBytesRcvd += bytesRcvd; //++ total bytes received
echoBuffer[bytesRcvd] = '\0'; //set last char to null cahr
printf(echoBuffer); //print received buffer
}
printf("\n");
}
close(sock);
exit(0);
}
,这是echoServer。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#define RCV_BUF_SIZE 512 //receive buffer size
#define MAX_BACKLOG 5
int main(int argc, char *argv[])
{
struct sockaddr_in echoServAddr, echoClntAddr; //define socket address(server, client)
int servSock, clntSock; //socket
unsigned short echoServPort; //port
unsigned int clntLen; //client address length
char echoBuffer[RCV_BUF_SIZE]; //receive buffer
int recvMsgSize; //received msg size
printf("echooo!\n\n");
echoServPort = atoi(argv[1]);
if((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) //socket creation failed
{
printf("socket() failed\n");
exit(1);
}
if(argc != 2) //if there are no right arguements, throw error and end program
{
printf("Usage : %s port\n", argv[0]);
exit(1);
}
memset(&echoServAddr, 0, sizeof(echoServAddr)); //memory reset
echoServAddr.sin_family = AF_INET; //define server address type
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);
if(bind(servSock, (struct sockaddr *)&echoServAddr, sizeof(echoServAddr))<0)//bind try, return -1 if error
{
printf("bind() failed, socket number : %d\n", servSock);
perror("Error : ");
exit(1);
}
if(listen(servSock, MAX_BACKLOG) < 0)//listen try, return -1 if error
{
printf("listen(failed\n");
exit(1);
}
while(1)
{
clntLen = sizeof(echoClntAddr);
if((clntSock = accept(servSock, (struct sockaddr*)&echoClntAddr, &clntLen))<0)//accept try, return -1 if error
{
printf("recv() failed\n");
exit(1);
}
while(1)
{
if((recvMsgSize = recv(clntSock, echoBuffer, RCV_BUF_SIZE, 0)) < 0)//recv try, return -1 if error
{
printf("recv() failed\n");
exit(1);
}
if(!strcmp(echoBuffer, "\/exit"))
{
break;
}
if(send(clntSock, echoBuffer, recvMsgSize, 0) != recvMsgSize)//send try, if sended bytes are shorter than recved bytes: throw error
{
printf("send() failed\n");
exit(1);
}
}
}
close(clntSock);
}
这是简单的描述。
服务器启动并继续收听。
客户端连接。
客户端从用户获取echo字,并将其发送到服务器。
服务器接收并返回它们。
重复,但一旦用户输入&#34; /退出&#34;,客户端发送&#34; /退出&#34;,并关闭套接字。
并且服务器收到&#34; / exit&#34;,服务器关闭套接字并退出。
但是,这就是问题所在。 服务器可以向客户端发送回显字,但是服务器进程有时会发送回#。当客户端发送&#34; /退出&#34;时终止,没有任何符号。我不知道为什么,但并非总是如此。
我试图将perror()
放在内部while循环的末尾,或者外部while循环,但我无法弄明白。
如果有人帮我解决这个服务器问题,我会很高兴。