【发布时间】:2020-09-28 12:03:21
【问题描述】:
我是套接字编程的新手,我从 Lewis Van Winkle - Hands-On Network Programming with C 那里得到了 TCP 编程的介绍。这是我的第一个问题,如果有的话,请指出。
对于来自注册或登录页面的 POST REQUEST,套接字会自行关闭。
有时甚至对于 GET 请求,经过一些延迟后,recv() 函数返回 0 并且不发送任何数据;
一点帮助或朝着正确的方向轻推会有所帮助
我的代码如下:-
#if defined(_WIN32)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include<io.h>
#include <process.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include<sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#endif
#if defined(_WIN32)
#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET)
#define CLOSESOCKET(s) closesocket(s)
#define GETSOCKETERRNO() (WSAGetLastError())
#else
#define ISVALIDSOCKET(s) ((s) >= 0)
#define CLOSESOCKET(s) close(s)
#define SOCKET int
#define GETSOCKETERRNO() (errno)
#endif
#if defined(_WIN32)
#else
#define mkdir(s) mkdir(s,0666)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ReadFrom(char uri[], char buffer[],SOCKET c1){
sprintf(buffer, "HTTP/1.1 200 OK\r\n");
send(c1, buffer, strlen(buffer), 0);
sprintf(buffer, "Connection: close \r\n");
send(c1, buffer, strlen(buffer), 0);
sprintf(buffer, "Content-Type: text/html\r\n");
send(c1, buffer, strlen(buffer), 0);
printf("\ntillhere23\n");
sprintf(buffer, "\r\n");
printf("\ntillhere23\n");
send(c1, buffer, strlen(buffer), 0);
char filename[30]="./public/";
strcat(filename,uri);
printf("\ntillhere23\n");
strcat(filename,".html");
FILE *fp=fopen(filename,"rb");
printf("\ntillhere23 %s %d %c \n",filename,fp,fp);
fseek(fp, 0L, SEEK_END);
printf("\ntillhere23 %s\n",filename);
size_t cl = ftell(fp);
printf("\ntillhere23 %s\n",filename);
rewind(fp);
printf("\ntillhere23 %s\n",filename);
printf("%s helo :: \n",buffer);
int r = fread(buffer, 1, 1024, fp);
while (r) {
send(c1, buffer, r, 0);
r = fread(buffer, 1, 1024, fp);
}
fclose(fp);
}
int main(){
#if defined(_WIN32)
WSADATA d;
if (WSAStartup(MAKEWORD(2, 2), &d)) {
fprintf(stderr, "Failed to initialize.\n");
return 1;
}
#endif
printf("Configuring local address...\n");
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *bind_address;
getaddrinfo("127.0.0.1","8080", &hints, &bind_address);
printf("Creating socket...\n");
SOCKET socket_listen;
socket_listen = socket(bind_address->ai_family,
bind_address->ai_socktype, bind_address->ai_protocol);
if (!ISVALIDSOCKET(socket_listen)) {
fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
exit(1);
}
printf("Binding socket to local address...\n");
if (bind(socket_listen,
bind_address->ai_addr, bind_address->ai_addrlen)) {
fprintf(stderr, "bind() failed. (%d)\n", GETSOCKETERRNO());
exit(1);
}
freeaddrinfo(bind_address);
SOCKET Server=socket_listen;
SOCKET c1=-1;
struct sockaddr_storage client_address;
socklen_t client_len = sizeof(client_address);
while(1){
printf("Listening...\n");
if (listen(socket_listen, 10) < 0) {
fprintf(stderr, "listen() failed. (%d)\n", GETSOCKETERRNO());
exit(1);
}
c1 = accept(socket_listen,
(struct sockaddr*) &client_address,
&client_len);
printf("CAME BACK %d\n",c1);
printf("CAME BACK2 :: %d\n",c1);
char buffer[1024];
char req[1024];
printf("receiving starts now::\n");
printf("STATUS OF RECV: %d",recv(c1,req,1024,0));
printf("\nRCV:\n%s\n",req);
/*for(int i=0;i<strlen(req);i++){
printf("\ni::%d ,char: %c, num:%d\n",i,req[i],req[i]);
}
printf("\n ABOVE CONTAINS ALLREQuests IN ASCII\n");*/
if(req[0]=='G' &&req[1]=='E'&& req[2]=='T')
{ printf("\nEntered GET\n");
if(strstr(req,"username")==NULL){
if(strstr(req,"/Login.html HTTP/1.1")!=NULL)
{
printf("\nenetered login\n");
ReadFrom("Login",buffer,c1);
CLOSESOCKET(c1);
}
else if(strstr(req,"/Logout.html HTTP/1.1")!=NULL)
{
CLOSESOCKET(c1);
CLOSESOCKET(Server);
printf("closed");
exit(0);
}
else if(strstr(req,"/Signup.html HTTP/1.1")!=NULL)
{
printf("\nenetered signup\n");
ReadFrom("Signup",buffer,c1);
CLOSESOCKET(c1);
printf("WHY CLOSE");
}
else
{
printf("\nenetered index\n");
ReadFrom("index",buffer,c1);
}
}
else {
printf("INSTEAD \n");
if(strstr(req,"/Move.html HTTP/1.1")!=NULL)
{
printf("\nenetered Move\n");
MainRead(0,buffer,c1,1,USERNAMEnum);
}
else if(strstr(req,"/Read.html?Category=")!=NULL)
{char Category[20];
char Patid[20];
wordify(req,"Category=","?",Category);
wordify(req,"Patid=","?",Patid);
ReadFrom("Read",buffer,c1);
}
else if(strstr(req,"/Write.html HTTP/1.1")!=NULL)
{
printf("\nenetered write\n");
char Category[20];
char Patid[20];
wordify(req,"Category=","?",Category);
wordify(req,"Patid=","?",Patid);
ReadFrom("Read",buffer,c1);
}
else if(strstr(req,"/New.html HTTP/1.1")!=NULL)
{
printf("\nenetered New\n");
MainRead(0,buffer,c1,4,USERNAMEnum);
}
else if(strstr(req,"/Logout.html HTTP/1.1")!=NULL)
{
CLOSESOCKET(c1);
CLOSESOCKET(Server);
printf("closed");
exit(0);
}
else{
MainRead(0,buffer,c1,0,USERNAMEnum);
}
}
}
else if(req[0]=='P' && req[1]=='O' && req[2]=='S' && req[3]=='T')
{printf("came here to POST:\n");
if(strstr(req,"/table1.html HTTP/1.1")!=NULL)
{printf("came here to TABLE\n");
printf("GOT::TABLE\n");
wordify(req,"Sno=","&",User.doctor_name);
StoI(User.doctor_name,&User.serialno);
wordify(req,"username=","&",User.username);
wordify(req,"&pswd=","\b",User.password);
if(Login(User)==0){
//Code for error
}
else{
ItoS(USERNAMEnum,Login(User));
}
MainRead(0,buffer,c1,0,USERNAMEnum);
printf("LOL");
}else if (strstr(req,"/Signup.html HTTP/1.1")!=NULL){
printf("\nenetered SIgnup in POST\n");
wordify(req,"Sno1=","&",User.doctor_name);
StoI(User.doctor_name,&User.serialno);
wordify(req,"&Name=","&",User.doctor_name);
wordify(req,"&Phoneno=","&",User.username);
StoI(User.username,&User.Phoneno);
wordify(req,"&Hospitalname=","&",User.hostipal_name);
wordify(req,"&State1=","&",User.state);
wordify(req,"&username1=","&",User.username);
wordify(req,"&pswd1=","\b",User.password);
printf("THE NUMBER:: %u ul \n",User.serialno);
Signup(User);
ReadFrom("Login",buffer,c1);
printf("Signup success\n");
CLOSESOCKET(c1);
}
}
/* else{
CLOSESOCKET(c1);
CLOSESOCKET(Server);
printf("closed");
exit(0);
}*/
}
return 1;
}
【问题讨论】:
-
recv返回 0 通常意味着远程对等方执行的优雅套接字关闭。我不清楚的是,在关闭之前您是否获得了预期的数据。 -
在被动延迟后,当客户端发送数据时,套接字关闭,但对于来自的 Post 请求,客户端在关闭前收到预期的数据
-
所以你所经历的可能是预期的关闭。服务器说“我发送了您请求的所有数据。祝您有美好的一天。PS:如果您需要更多连接,请打开一个新套接字”。这是我多年来没有处理过的事情,但如果我没记错的话,闭包行为是可以从服务器端以某种方式配置的。
-
谢谢你的提示,但如果你注意到了,这里发布的代码是服务器代码,我不会关闭绑定到端口 80 的 Server_listen 套接字,我正在使用我的浏览器作为一个客户端来访问它。尽管如此,服务器套接字还是关闭了,我想知道这个原因。感谢您的努力
-
在调用它们的位置之后定义的所有函数,都需要在
#include语句之后的原型。否则,编译器会输出大量警告和错误消息。也就是说,贴出来的代码不能编译!