C中的套接字和服务器问题(名称或服务未知错误)
我正在开发一个客户机/服务器程序,该程序应该接受用户输入(两个整数),并允许用户计算这些输入以接收答案 当我运行我的程序时,连接到客户机或打开目录似乎有问题,我不确定这可能是什么问题。我对设置服务器和使用目录读写.txt文件是完全陌生的 下面是我认为可能是错误的代码部分,这些代码导致了我面临的问题,即程序要求连接到一个端口号(建议使用2000),因此我输入该端口号,然后什么也没有发生C中的套接字和服务器问题(名称或服务未知错误),c,sockets,error-handling,server,client,C,Sockets,Error Handling,Server,Client,我正在开发一个客户机/服务器程序,该程序应该接受用户输入(两个整数),并允许用户计算这些输入以接收答案 当我运行我的程序时,连接到客户机或打开目录似乎有问题,我不确定这可能是什么问题。我对设置服务器和使用目录读写.txt文件是完全陌生的 下面是我认为可能是错误的代码部分,这些代码导致了我面临的问题,即程序要求连接到一个端口号(建议使用2000),因此我输入该端口号,然后什么也没有发生 // PURPOSE: To run the server by 'accept()'-ing clie
// PURPOSE: To run the server by 'accept()'-ing client requests from
// 'listenFd' and doing them.
void doServer (int listenFd)
{
/* Application validity check: */
/* Server clients: */
pthread_t threadId;
pthread_attr_t threadAttr;
int threadCount = 0;
int *iPtr;
/* YOUR CODE HERE: */
while(1)
{
/* Accept connection to client: */
int connfd = accept(listenFd, NULL, NULL); //if I change this to getServerFileDescriptor (another function within the code, it will continuously loop through threadNumbers and do nothing as well).
/* Malloc memory for two integers: */
iPtr = (int *)calloc(2, sizeof(int));
/*Put file descriptor in the first space: */
iPtr[0] = listenFd; // or just listenFd not sure
/* put threadCount into the second space and increment: */
iPtr[1] = threadCount++;
/* Creates detached thread for handleClient and passes the address of iPtr */
pthread_attr_init(&threadAttr);
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
pthread_create(&threadId, &threadAttr, handleClient, (void*)iPtr);
pthread_join(threadId, NULL);
pthread_attr_destroy(&threadAttr);
}
}
void* handleClient(void* vPtr)
{
/* Read command: */
char buffer[BUFFER_LEN];
char command;
int fileNum;
char text[BUFFER_LEN];
int shouldContinue = 1;
int threadNum;
int fd;
/* Cast void* vPtr back to an int */
int *iPtr = (int *)vPtr;
/* Assign file descriptor to a local value named 'fd'*/
fd = iPtr[0];
/* Assign thread number to local value named 'threadNum'*/
threadNum = iPtr[1];
free(iPtr);
while (shouldContinue)
{
memset(buffer,'\0',BUFFER_LEN);
memset(text ,'\0',BUFFER_LEN);
read(fd,buffer,BUFFER_LEN);
printf("Thread %d received: %s\n",threadNum,buffer);
sscanf(buffer,"%c %d \"%[^\"]\"",&command,&fileNum,text);
/* YOUR CODE HERE: */
if(command == DIR_CMD_CHAR)
{
/* 1. Open the current directory (named "."). If an error occurs then just send STD_ERROR_MSG back to the client: */
DIR* dirPtr = opendir(".");
struct dirent* entryPtr;
/* If error occurs send STD_ERROR_MSG to client: */
if ((dirPtr = opendir (".")) == NULL) {
{
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
//return(EXIT_FAILURE);
}
/* Read as many entries that will fit into BUFFER_LEN
put as many entries into the buffer and send the buffer to client
d_name=entryPtr into the bufffer using strcat_s,
make sure buffer starts empty
buffer[0]='\n';
add new line char using stringcat "\n"
make sure do not go over buffer lengh */
if (dirPtr)
{
while ((entryPtr = readdir(dirPtr)) != NULL)
{
buffer[0]='\0';
int i;
int sizebuf = sizeof(buffer);
for (i = 0; i < sizebuf; i++)
{
strcat(buffer,entryPtr->d_name);
strcat(buffer,"\n");
}
}
}
/* 3. Close directory */
closedir(dirPtr);
}
它将()从客户端读取一行文本到缓冲区[],并将该行解析为命令字符、fileNum integer和引号分隔的文本[]字符串。(fileNum和text[]可以给定,也可以不给定,具体取决于命令的值。)
然后根据命令的值执行以下操作。除了QUIT\u CMD\u CHAR之外,我强烈建议对每个函数使用不同的函数
当函数结束时,让它执行以下操作:
printf("Thread %d quitting.\n",threadNum);
return(NULL);
command==DIR\u CMD\u CHAR(15分):
打开当前目录(名为“.”)。如果发生错误,只需将STD_error_MSG发送回客户端。
复制尽可能多的条目,将其放入长度为buffer_LEN的缓冲区中。请确保在每个条目后面加一个分隔的“\n”。
关闭目录
任何帮助将不胜感激,如果你需要完整的代码,我可以发送给你,如果这会有所帮助
编辑:这里有两个附加函数,一个名为getPortNum(),另一个名为getServerFileDescriptor(),用于处理接收端口号和为连接设置套接字的问题。此外,我还包括了main(),它利用了这些
// PURPOSE: To decide a port number, either from the command line arguments
// 'argc' and 'argv[]', or by asking the user. Returns port number.
int getPortNum (int argc,
char* argv[]
)
{
// I. Application validity check:
// II. Get listening socket:
int portNum;
if (argc >= 2)
portNum = strtol(argv[1],NULL,0);
else
{
char buffer[BUFFER_LEN];
printf("Port number to monopolize? ");
fgets(buffer,BUFFER_LEN,stdin);
portNum = strtol(buffer,NULL,0);
}
// III. Finished:
return(portNum);
}
// PURPOSE: To attempt to create and return a file-descriptor for listening
// to the OS telling this server when a client process has connect()-ed
// to 'port'. Returns that file-descriptor, or 'ERROR_FD' on failure.
int getServerFileDescriptor
(int port
)
{
// I. Application validity check:
// II. Attempt to get socket file descriptor and bind it to 'port':
// II.A. Create a socket
int socketDescriptor = socket(AF_INET, // AF_INET domain
SOCK_STREAM, // Reliable TCP
0);
if (socketDescriptor < 0)
{
perror(THIS_PROGRAM_NAME);
return(ERROR_FD);
}
// II.B. Attempt to bind 'socketDescriptor' to 'port':
// II.B.1. We'll fill in this datastruct
struct sockaddr_in socketInfo;
// II.B.2. Fill socketInfo with 0's
memset(&socketInfo,'\0',sizeof(socketInfo));
// II.B.3. Use TCP/IP:
socketInfo.sin_family = AF_INET;
// II.B.4. Tell port in network endian with htons()
socketInfo.sin_port = htons(port);
// II.B.5. Allow machine to connect to this service
socketInfo.sin_addr.s_addr = INADDR_ANY;
// II.B.6. Try to bind socket with port and other specifications
int status = bind(socketDescriptor, // from socket()
(struct sockaddr*)&socketInfo,
sizeof(socketInfo)
);
if (status < 0)
{
perror(THIS_PROGRAM_NAME);
return(ERROR_FD);
}
// II.B.6. Set OS queue length:
listen(socketDescriptor,5);
// III. Finished:
return(socketDescriptor);
}
int main (int argc,
char* argv[]
)
{
// I. Application validity check:
// II. Do server:
int port = getPortNum(argc,argv);
int listenFd = getServerFileDescriptor(port);
int status = EXIT_FAILURE;
if (listenFd >= 0)
{
doServer(listenFd);
close(listenFd);
status = EXIT_SUCCESS;
}
// III. Finished:
return(status);
//目的:从命令行参数中确定端口号
//“argc”和“argv[]”,或询问用户。返回端口号。
int getPortNum(int argc,
字符*argv[]
)
{
//一、申请有效性检查:
//二、获取监听插座:
int-portNum;
如果(argc>=2)
portNum=strtol(argv[1],NULL,0);
其他的
{
字符缓冲区[buffer_LEN];
printf(“要垄断的端口号?”);
fgets(缓冲器、缓冲器、标准装置);
portNum=strtol(缓冲区,NULL,0);
}
//三、完成:
返回(portNum);
}
//目的:尝试创建并返回用于侦听的文件描述符
//当客户端进程已连接()时通知此服务器的操作系统
//到“端口”。返回该文件描述符,或失败时返回“ERROR\u FD”。
int getServerFileDescriptor
(内部端口)
)
{
//一、申请有效性检查:
//II.尝试获取套接字文件描述符并将其绑定到“端口”:
//II.A.创建一个插座
int-socketDescriptor=socket(AF_INET,//AF_INET域
SOCK\u流,//可靠的TCP
0);
if(socketDescriptor<0)
{
perror(该项目名称);
返回(错误\u FD);
}
//II.B.尝试将“socketDescriptor”绑定到“端口”:
//II.B.1.我们将填写此数据结构
socketInfo中的结构sockaddr_;
//II.B.2.用0填充socketInfo
memset(&socketInfo,'\0',sizeof(socketInfo));
//II.B.3.使用TCP/IP:
socketInfo.sin_family=AF_INET;
//II.B.4.用htons()在网络端告诉端口
socketInfo.sinu端口=htons(端口);
//II.B.5.允许机器连接到此服务
socketInfo.sinu addr.s\u addr=INADDR\u ANY;
//II.B.6.尝试将插座与端口和其他规格绑定
int status=bind(socketDescriptor,//来自socket()
(结构sockaddr*)和socketInfo,
sizeof(socketInfo)
);
如果(状态<0)
{
perror(该项目名称);
返回(错误\u FD);
}
//II.B.6.设置操作系统队列长度:
听(socketDescriptor,5);
//三、完成:
返回(socketDescriptor);
}
int main(int argc,
字符*argv[]
)
{
//一、申请有效性检查:
//二、做服务器:
int port=getPortNum(argc,argv);
int listenFd=getServerFileDescriptor(端口);
int status=退出故障;
如果(listenFd>=0)
{
doServer(listenFd);
关闭(listenFd);
状态=退出\成功;
}
//三、完成:
返回(状态);
Nevermind,我编辑了原始帖子并将其包括在内。您好,您能添加一个您在服务器和客户端之间实现的协议的描述吗?这是因为我看到这行代码可能有问题:sscanf(缓冲区,“%c%d\”%[^\“]\”,&command,&fileNum,text);
。
// PURPOSE: To decide a port number, either from the command line arguments
// 'argc' and 'argv[]', or by asking the user. Returns port number.
int getPortNum (int argc,
char* argv[]
)
{
// I. Application validity check:
// II. Get listening socket:
int portNum;
if (argc >= 2)
portNum = strtol(argv[1],NULL,0);
else
{
char buffer[BUFFER_LEN];
printf("Port number to monopolize? ");
fgets(buffer,BUFFER_LEN,stdin);
portNum = strtol(buffer,NULL,0);
}
// III. Finished:
return(portNum);
}
// PURPOSE: To attempt to create and return a file-descriptor for listening
// to the OS telling this server when a client process has connect()-ed
// to 'port'. Returns that file-descriptor, or 'ERROR_FD' on failure.
int getServerFileDescriptor
(int port
)
{
// I. Application validity check:
// II. Attempt to get socket file descriptor and bind it to 'port':
// II.A. Create a socket
int socketDescriptor = socket(AF_INET, // AF_INET domain
SOCK_STREAM, // Reliable TCP
0);
if (socketDescriptor < 0)
{
perror(THIS_PROGRAM_NAME);
return(ERROR_FD);
}
// II.B. Attempt to bind 'socketDescriptor' to 'port':
// II.B.1. We'll fill in this datastruct
struct sockaddr_in socketInfo;
// II.B.2. Fill socketInfo with 0's
memset(&socketInfo,'\0',sizeof(socketInfo));
// II.B.3. Use TCP/IP:
socketInfo.sin_family = AF_INET;
// II.B.4. Tell port in network endian with htons()
socketInfo.sin_port = htons(port);
// II.B.5. Allow machine to connect to this service
socketInfo.sin_addr.s_addr = INADDR_ANY;
// II.B.6. Try to bind socket with port and other specifications
int status = bind(socketDescriptor, // from socket()
(struct sockaddr*)&socketInfo,
sizeof(socketInfo)
);
if (status < 0)
{
perror(THIS_PROGRAM_NAME);
return(ERROR_FD);
}
// II.B.6. Set OS queue length:
listen(socketDescriptor,5);
// III. Finished:
return(socketDescriptor);
}
int main (int argc,
char* argv[]
)
{
// I. Application validity check:
// II. Do server:
int port = getPortNum(argc,argv);
int listenFd = getServerFileDescriptor(port);
int status = EXIT_FAILURE;
if (listenFd >= 0)
{
doServer(listenFd);
close(listenFd);
status = EXIT_SUCCESS;
}
// III. Finished:
return(status);