无法在 Socket 编程中将 int 从服务器发送到客户端
Cannot send int from Server to Client in Socket Programming
我是套接字编程的新手,正在尝试制作一个服务器-客户端程序,在该程序中,客户端首先发送文件名,然后服务器打开该文件并计算文件的大小并将大小发回给客户。
虽然在服务器端,我可以计算文件的大小,但无法将其发送回客户端。
我得到 filesize
作为 0。
代码如下:
服务器
#include<iostream>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
using namespace std;
int filesize(char* fname){
FILE *f=fopen(fname,"r");
fseek(f,0,SEEK_END);
int len=ftell(f);
fclose(f);
//cout<<"\nlength= "<<len;
return len;
}
int main(){
int sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid<0){
cout<<"Failed Creating socket\n";
return 0;
}
int client_socket;
struct sockaddr_in server, client;
int client_size=sizeof(client);
server.sin_family=AF_INET;
server.sin_port=htons(8791);
server.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockid,(struct sockaddr*)&server,sizeof(server))<0){
cout<<"Failed binding\n";
return 0;
}
cout<<"binded";
if(listen(sockid,4)<0){
cout<<"Failed listening\n";
return 0;
}
cout<<"Listening....\n";
if((client_socket=accept(sockid,(struct sockaddr*)&client, (socklen_t*)&(client_size)))<0){
cout<<"Failed accepting\n";
return 0;
}
cout<<"Connecting\n";
char fname[]={0};
int x=recv(client_socket,fname,1024,0);
cout<<fname<<endl;
//char fname[]={"a.txt"};
fname[x]='[=10=]';
int fsize=filesize(fname);
cout<<"FILE SIZE : "<<fsize<<endl;
//int fsize=58;
if(send(client_socket,&fsize,sizeof(int),0)<0){
cout<<"failed sending SIZE\n";
return 0;
}
return 0;
}
客户代码:
#include<iostream>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
using namespace std;
int main(){
int sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid<0){cout<<"Failed creating socket\n";return 0;}
struct sockaddr_in client;
client.sin_family=AF_INET;
client.sin_port=htons(8797);
client.sin_addr.s_addr=htonl(INADDR_ANY);
if(connect(sockid,(struct sockaddr*)&client,sizeof(client))<0){
cout<<"Failed connecting\n";
return 0;
}
cout<<"Connected\n";
cout<<"Enter File name : ";
char fname[1024];
cin>>fname;
if(send(sockid,fname,strlen(fname),0)<0){
cout<<"Failed receiving\n";
}
int fsize;
if(recv(sockid,&fsize,sizeof(int),0)<0){
cout<<"failed receiving file_size\n";
return 0;
}
cout<<"\nFILE-SIZE : "<<fsize;
return 0;
}
TCP是字节流。 send()
和 recv()
可以比请求的字节少 return,因此您需要在循环中调用它们以确保您 send/recv 所有您期望的字节。
此外,您需要以这样一种方式构建您的消息,即您知道一条消息的结束位置和下一条消息的开始位置。
此外,整数应始终使用固定宽度的整数类型传输,多字节整数应始终以网络字节顺序(大端)传输,以实现跨平台边界的一致性。
尝试这样的事情:
服务器
#include <iostream>
#include <string>
#include <limits>
#include <cstdint>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
bool filesize(const std::string &fname, std::uint32_t &fsize)
{
FILE *f = fopen(fname.c_str(), "rb");
if (!f)
{
std::cout << "Failed opening file\n";
return false;
}
if (fseek(f, 0, SEEK_END) != 0)
{
std::cout << "Failed seeking file\n";
fclose(f);
return false;
}
long len = ftell(f);
fclose(f);
if (len == -1L)
{
std::cout << "Failed getting file size\n";
return false;
}
if (sizeof(long) > sizeof(std::uint32_t))
{
if (len > std::numeric_limits<std::uint32_t>::max())
{
std::cout << "File size exceeds uint32_t max\n";
return false;
}
}
fsize = static_cast<std::uint32_t>(len);
return true;
}
int readAll(int sock, void *buffer, int buflen)
{
char *ptr = static_cast<char*>(buffer);
int x;
while (buflen > 0)
{
x = recv(sock, ptr, buflen, 0);
if (x <= 0)
{
if (x == 0)
std::cout << "Client disconnected\n";
else
std::cout << "Failed reading socket, error " << errno << "\n";
return x;
}
ptr += x;
buflen -= x;
}
return 1;
}
int readUInt32(int sock, std::uint32_t &value)
{
int x = readAll(sock, &value, sizeof(value));
if (x <= 0) return x;
value = ntohl(value);
return 1;
}
int readString(int sock, std::string &s)
{
s.clear();
// approach 1: null-terminated string
char buffer[1024];
int x, offset = 0;
do
{
x = readAll(sock, &buffer[offset], 1);
if (x <= 0)
return x;
if (buffer[offset] == '[=10=]')
break;
if (++offset == sizeof(buffer))
{
s.append(buffer, offset);
offset = 0;
}
}
while (true);
if (offset > 0)
s.append(buffer, offset);
return 1;
// approach 2: length-prefixed string
std::uint32_t size;
int x = readUInt32(sock, size);
if ((x > 0) && (size > 0))
{
s.resize(size);
x = readAll(sock, &s[0], size);
}
if (x <= 0)
return x;
return 1;
}
bool sendAll(int sock, const void *buffer, int buflen)
{
const char *ptr = static_cast<const char*>(buffer);
int x;
while (buflen > 0)
{
x = send(sock, ptr, buflen, 0);
if (x < 0)
{
std::cout << "Failed sending socket, error " << errno << "\n";
return false;
}
ptr += x;
buflen -= x;
}
return true;
}
bool sendBool(int sock, bool value)
(
std::uint8_t temp = value;
return sendAll(sock, &temp, sizeof(temp));
}
bool sendUInt32(int sock, std::uint32_t value)
{
value = htonl(value);
return sendAll(sock, &value, sizeof(value));
}
int main()
{
int sockid = socket(AF_INET, SOCK_STREAM, 0);
if (sockid < 0)
{
std::cout << "Failed creating socket, error " << errno << "\n";
return 0;
}
int client_socket;
struct sockaddr_in server, client;
socklen_t client_size;
server.sin_family = AF_INET;
server.sin_port = htons(8791);
server.sin_addr.s_addr = htonl(INADDR_ANY);
socklen_t client_size;
if (bind(sockid, (struct sockaddr*)&server, sizeof(server)) < 0)
{
std::cout << "Failed binding socket, error " << errno << "\n";
close(sockid);
return 0;
}
std::cout << "Binded";
if (listen(sockid, 4) < 0)
{
std::cout << "Failed listening socket, error " << errno << "\n";
close(sockid);
return 0;
}
std::cout << "Listening....\n";
client_size = sizeof(client);
if ((client_socket = accept(sockid, (struct sockaddr*)&client, &client_size)) < 0)
{
std::cout << "Failed accepting client socket\n";
close(sockid);
return 0;
}
std::cout << "Client connected\n";
std::string fname;
if (readString(client_socket, fname) <= 0)
{
close(client_socket);
close(sockid);
return 0;
}
std::cout << fname << "\n";
std::uint32_t fsize;
bool success = filesize(fname, fsize);
if (!sendBool(client_socket, success))
{
std::cout << "Failed sending file size reply\n";
}
else if (success)
{
std::cout << "FILE SIZE : " << fsize << std::endl;
if (!sendUInt32(client_socket, fsize))
std::cout << "Failed sending file size\n";
}
close(client_socket);
close(sockid);
return 0;
}
客户
#include <iostream>
#include <string>
#include <cstdint>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
int readAll(int sock, void *buffer, int buflen)
{
char *ptr = static_cast<char*>(buffer);
int x;
while (buflen > 0)
{
x = recv(sock, ptr, buflen, 0);
if (x <= 0)
{
if (x == 0)
std::cout << "Server disconnected\n";
else
std::cout << "Failed reading socket, error " << errno << "\n";
return x;
}
ptr += x;
buflen -= x;
}
return 1;
}
int readBool(int sock, bool &value)
{
std::uint8_t temp;
int x = readAll(sock, &temp, sizeof(temp));
if (x <= 0) return x;
value = (temp != 0);
return 1;
}
int readUInt32(int sock, std::uint32_t &value)
{
int x = readAll(sock, &value, sizeof(value));
if (x <= 0) return x;
value = ntohl(value);
return 1;
}
bool sendAll(int sock, const void *buffer, int buflen)
{
const char *ptr = static_cast<const char*>(buffer);
int x;
while (buflen > 0)
{
x = send(sock, ptr, buflen, 0);
if (x < 0)
{
std::cout << "Failed sending socket, error " << errno << "\n";
return false;
}
ptr += x;
buflen -= x;
}
return true;
}
bool sendString(int sock, const std::string &s)
{
// approach 1: null-terminated string
return sendAll(sock, s.c_str(), s.size()+1);
// approach 2: length-prefixed string
std::uint32_t size = s.size();
return sendUInt32(sock, size) && sendAll(sock, s.c_str(), size);
}
int main()
{
int sockid = socket(AF_INET, SOCK_STREAM, 0);
if (sockid < 0)
{
std::cout << "Failed creating socket, error " << errno << "\n";
return 0;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(8797);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sockid, (struct sockaddr*)&server, sizeof(server)) < 0)
{
std::cout << "Failed connecting socket, error " << errno << "\n";
close(sockid);
return 0;
}
std::cout << "Connected\n";
std::cout << "Enter File name : ";
std::string fname;
std::getline(std::cin, fname);
if (!sendString(sockid, fname))
{
std::cout << "Failed sending file name\n";
close(sockid);
return 0;
}
bool success;
if (readBool(sockid, success) <= 0)
{
std::cout << "Failed receiving file size reply\n";
close(sockid);
return 0;
}
if (success)
{
std::uint32_t fsize;
if (readUInt32(sockid, fsize) <= 0)
{
std::cout << "Failed receiving file size\n";
close(sockid);
return 0;
}
std::cout << "FILE-SIZE : " << fsize << "\n";
}
else
std::cout << "FILE-SIZE error\n";
close(sockid);
return 0;
}
我是套接字编程的新手,正在尝试制作一个服务器-客户端程序,在该程序中,客户端首先发送文件名,然后服务器打开该文件并计算文件的大小并将大小发回给客户。
虽然在服务器端,我可以计算文件的大小,但无法将其发送回客户端。
我得到 filesize
作为 0。
代码如下:
服务器
#include<iostream>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
using namespace std;
int filesize(char* fname){
FILE *f=fopen(fname,"r");
fseek(f,0,SEEK_END);
int len=ftell(f);
fclose(f);
//cout<<"\nlength= "<<len;
return len;
}
int main(){
int sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid<0){
cout<<"Failed Creating socket\n";
return 0;
}
int client_socket;
struct sockaddr_in server, client;
int client_size=sizeof(client);
server.sin_family=AF_INET;
server.sin_port=htons(8791);
server.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockid,(struct sockaddr*)&server,sizeof(server))<0){
cout<<"Failed binding\n";
return 0;
}
cout<<"binded";
if(listen(sockid,4)<0){
cout<<"Failed listening\n";
return 0;
}
cout<<"Listening....\n";
if((client_socket=accept(sockid,(struct sockaddr*)&client, (socklen_t*)&(client_size)))<0){
cout<<"Failed accepting\n";
return 0;
}
cout<<"Connecting\n";
char fname[]={0};
int x=recv(client_socket,fname,1024,0);
cout<<fname<<endl;
//char fname[]={"a.txt"};
fname[x]='[=10=]';
int fsize=filesize(fname);
cout<<"FILE SIZE : "<<fsize<<endl;
//int fsize=58;
if(send(client_socket,&fsize,sizeof(int),0)<0){
cout<<"failed sending SIZE\n";
return 0;
}
return 0;
}
客户代码:
#include<iostream>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
using namespace std;
int main(){
int sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid<0){cout<<"Failed creating socket\n";return 0;}
struct sockaddr_in client;
client.sin_family=AF_INET;
client.sin_port=htons(8797);
client.sin_addr.s_addr=htonl(INADDR_ANY);
if(connect(sockid,(struct sockaddr*)&client,sizeof(client))<0){
cout<<"Failed connecting\n";
return 0;
}
cout<<"Connected\n";
cout<<"Enter File name : ";
char fname[1024];
cin>>fname;
if(send(sockid,fname,strlen(fname),0)<0){
cout<<"Failed receiving\n";
}
int fsize;
if(recv(sockid,&fsize,sizeof(int),0)<0){
cout<<"failed receiving file_size\n";
return 0;
}
cout<<"\nFILE-SIZE : "<<fsize;
return 0;
}
TCP是字节流。 send()
和 recv()
可以比请求的字节少 return,因此您需要在循环中调用它们以确保您 send/recv 所有您期望的字节。
此外,您需要以这样一种方式构建您的消息,即您知道一条消息的结束位置和下一条消息的开始位置。
此外,整数应始终使用固定宽度的整数类型传输,多字节整数应始终以网络字节顺序(大端)传输,以实现跨平台边界的一致性。
尝试这样的事情:
服务器
#include <iostream>
#include <string>
#include <limits>
#include <cstdint>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
bool filesize(const std::string &fname, std::uint32_t &fsize)
{
FILE *f = fopen(fname.c_str(), "rb");
if (!f)
{
std::cout << "Failed opening file\n";
return false;
}
if (fseek(f, 0, SEEK_END) != 0)
{
std::cout << "Failed seeking file\n";
fclose(f);
return false;
}
long len = ftell(f);
fclose(f);
if (len == -1L)
{
std::cout << "Failed getting file size\n";
return false;
}
if (sizeof(long) > sizeof(std::uint32_t))
{
if (len > std::numeric_limits<std::uint32_t>::max())
{
std::cout << "File size exceeds uint32_t max\n";
return false;
}
}
fsize = static_cast<std::uint32_t>(len);
return true;
}
int readAll(int sock, void *buffer, int buflen)
{
char *ptr = static_cast<char*>(buffer);
int x;
while (buflen > 0)
{
x = recv(sock, ptr, buflen, 0);
if (x <= 0)
{
if (x == 0)
std::cout << "Client disconnected\n";
else
std::cout << "Failed reading socket, error " << errno << "\n";
return x;
}
ptr += x;
buflen -= x;
}
return 1;
}
int readUInt32(int sock, std::uint32_t &value)
{
int x = readAll(sock, &value, sizeof(value));
if (x <= 0) return x;
value = ntohl(value);
return 1;
}
int readString(int sock, std::string &s)
{
s.clear();
// approach 1: null-terminated string
char buffer[1024];
int x, offset = 0;
do
{
x = readAll(sock, &buffer[offset], 1);
if (x <= 0)
return x;
if (buffer[offset] == '[=10=]')
break;
if (++offset == sizeof(buffer))
{
s.append(buffer, offset);
offset = 0;
}
}
while (true);
if (offset > 0)
s.append(buffer, offset);
return 1;
// approach 2: length-prefixed string
std::uint32_t size;
int x = readUInt32(sock, size);
if ((x > 0) && (size > 0))
{
s.resize(size);
x = readAll(sock, &s[0], size);
}
if (x <= 0)
return x;
return 1;
}
bool sendAll(int sock, const void *buffer, int buflen)
{
const char *ptr = static_cast<const char*>(buffer);
int x;
while (buflen > 0)
{
x = send(sock, ptr, buflen, 0);
if (x < 0)
{
std::cout << "Failed sending socket, error " << errno << "\n";
return false;
}
ptr += x;
buflen -= x;
}
return true;
}
bool sendBool(int sock, bool value)
(
std::uint8_t temp = value;
return sendAll(sock, &temp, sizeof(temp));
}
bool sendUInt32(int sock, std::uint32_t value)
{
value = htonl(value);
return sendAll(sock, &value, sizeof(value));
}
int main()
{
int sockid = socket(AF_INET, SOCK_STREAM, 0);
if (sockid < 0)
{
std::cout << "Failed creating socket, error " << errno << "\n";
return 0;
}
int client_socket;
struct sockaddr_in server, client;
socklen_t client_size;
server.sin_family = AF_INET;
server.sin_port = htons(8791);
server.sin_addr.s_addr = htonl(INADDR_ANY);
socklen_t client_size;
if (bind(sockid, (struct sockaddr*)&server, sizeof(server)) < 0)
{
std::cout << "Failed binding socket, error " << errno << "\n";
close(sockid);
return 0;
}
std::cout << "Binded";
if (listen(sockid, 4) < 0)
{
std::cout << "Failed listening socket, error " << errno << "\n";
close(sockid);
return 0;
}
std::cout << "Listening....\n";
client_size = sizeof(client);
if ((client_socket = accept(sockid, (struct sockaddr*)&client, &client_size)) < 0)
{
std::cout << "Failed accepting client socket\n";
close(sockid);
return 0;
}
std::cout << "Client connected\n";
std::string fname;
if (readString(client_socket, fname) <= 0)
{
close(client_socket);
close(sockid);
return 0;
}
std::cout << fname << "\n";
std::uint32_t fsize;
bool success = filesize(fname, fsize);
if (!sendBool(client_socket, success))
{
std::cout << "Failed sending file size reply\n";
}
else if (success)
{
std::cout << "FILE SIZE : " << fsize << std::endl;
if (!sendUInt32(client_socket, fsize))
std::cout << "Failed sending file size\n";
}
close(client_socket);
close(sockid);
return 0;
}
客户
#include <iostream>
#include <string>
#include <cstdint>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
int readAll(int sock, void *buffer, int buflen)
{
char *ptr = static_cast<char*>(buffer);
int x;
while (buflen > 0)
{
x = recv(sock, ptr, buflen, 0);
if (x <= 0)
{
if (x == 0)
std::cout << "Server disconnected\n";
else
std::cout << "Failed reading socket, error " << errno << "\n";
return x;
}
ptr += x;
buflen -= x;
}
return 1;
}
int readBool(int sock, bool &value)
{
std::uint8_t temp;
int x = readAll(sock, &temp, sizeof(temp));
if (x <= 0) return x;
value = (temp != 0);
return 1;
}
int readUInt32(int sock, std::uint32_t &value)
{
int x = readAll(sock, &value, sizeof(value));
if (x <= 0) return x;
value = ntohl(value);
return 1;
}
bool sendAll(int sock, const void *buffer, int buflen)
{
const char *ptr = static_cast<const char*>(buffer);
int x;
while (buflen > 0)
{
x = send(sock, ptr, buflen, 0);
if (x < 0)
{
std::cout << "Failed sending socket, error " << errno << "\n";
return false;
}
ptr += x;
buflen -= x;
}
return true;
}
bool sendString(int sock, const std::string &s)
{
// approach 1: null-terminated string
return sendAll(sock, s.c_str(), s.size()+1);
// approach 2: length-prefixed string
std::uint32_t size = s.size();
return sendUInt32(sock, size) && sendAll(sock, s.c_str(), size);
}
int main()
{
int sockid = socket(AF_INET, SOCK_STREAM, 0);
if (sockid < 0)
{
std::cout << "Failed creating socket, error " << errno << "\n";
return 0;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(8797);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sockid, (struct sockaddr*)&server, sizeof(server)) < 0)
{
std::cout << "Failed connecting socket, error " << errno << "\n";
close(sockid);
return 0;
}
std::cout << "Connected\n";
std::cout << "Enter File name : ";
std::string fname;
std::getline(std::cin, fname);
if (!sendString(sockid, fname))
{
std::cout << "Failed sending file name\n";
close(sockid);
return 0;
}
bool success;
if (readBool(sockid, success) <= 0)
{
std::cout << "Failed receiving file size reply\n";
close(sockid);
return 0;
}
if (success)
{
std::uint32_t fsize;
if (readUInt32(sockid, fsize) <= 0)
{
std::cout << "Failed receiving file size\n";
close(sockid);
return 0;
}
std::cout << "FILE-SIZE : " << fsize << "\n";
}
else
std::cout << "FILE-SIZE error\n";
close(sockid);
return 0;
}