我一直在尝试通过套接字将数据包从客户端发送到服务器。借助一些技巧,我在代码中取得了很大的进步。但是,服务器只从客户端接收八个字节并在控制台上打印它们,而在我的客户端,它似乎已经发送了所有内容。
现在我不确定问题是在发送方还是在接收方。我的预感是我的客户端出了问题。有人可以帮助验证我的假设吗?
客户代码:
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
data_struct client_data;
struct packet
{
long int srcID;
long int destID;
int pver;
int profiles;
int length;
long int data;
};
if (argc < 3) {
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]); //Convert ASCII to integer
sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR in connection");
printf("SUCCESS !!! Connection established \n");
char buffer[256];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long double packet_size;
printf("Started Creating packet\n");
pkt->srcID = 01;
pkt->destID = 02;
pkt->pver = 03;
pkt->profiles = 01;
pkt->length = 16;
pkt->data = 1; 2; 3; 4; 5; 6; 7; 8;
{
if (send(sockfd,pkt,sizeof(packet_size),0) <0)
printf ("error\n");
else
printf ("packet send done");
}
return 0;
}
服务器代码:
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
char wish;
long int SrcID;
long int DestID;
int Pver;
int Profiles;
long int Data;
int Length;
char bytes_to_receive;
int received_bytes;
struct packet
{
long int srcID;
long int destID;
int pver;
int profiles;
int length;
long int data;
};
if (argc < 2) {
fprintf(stderr,"usage: %s port_number1",argv[0]);
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR DETECTED !!! There was a problem in binding");
listen(sockfd, 10);
clilen = sizeof(cli_addr);
printf("Server listening on port number %d...\n", serv_addr.sin_port);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR DETECTED !!! the connection request was not accepted");
char buffer[256];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long double packet_size;
bytes_to_receive = sizeof(packet_size);
received_bytes = 0;
int rc =0;
while ((rc = recv(newsockfd,pkt,sizeof(packet_size),0)) > 0)
{
received_bytes+=rc;
SrcID = pkt->srcID;
DestID = pkt->destID;
Pver = pkt->pver ;
Profiles = pkt->profiles;
Length = pkt->length;
Data = pkt->data;
printf("Data Received from Client_1 are :\n");
printf("Source ID: %ld\n", SrcID);
printf("Destination ID: %ld\n", DestID);
printf("profile Version: %d\n", Pver);
printf("No of Profiles: %d\n", Profiles);
printf("Length: %d\n", Length);
printf("data : %ld\n", Data);
}
if (rc == 0)
{
printf("Connection closed by Server\n");
printf("Bytes received: %d\n",received_bytes);
}
if (rc == -1)
{
perror("recv");
}
{
if (close(newsockfd) == -1) {
error("Error closing connection with client 1");
}
printf("Connection with client 1 has been closed\n");
}
return 0;
}
我在客户端控制台上看到的输出是:
Client Side: Client 1 trying to connect with server host 130.191.166.230 on port 1234
SUCCESS !!! Connection established
Started Creating packet
packet send done
在服务器的控制台上我看到:
Server Side: Data Received from Client_1 are :
Source ID: 1
Destination ID: 2
profile Version: 0
No of Profiles: 1074462536
Length: 0
data : 0
Connection closed by Server
Bytes received: 8
Connection with client 1 has been closed
答案 0 :(得分:2)
首先
recv(newsockfd,pkt,sizeof(packet_size),0)) /* What is packet_size ? */
recv(newsockfd,pkt,sizeof(struct packet),0)) /* You probably mean this. */
这可能会解决您的问题,但使用TCP套接字的方式存在一些问题。
但是在我的客户端,它打印出它发送了所有内容
在哪里?我没有看到你实际检查发送的字节数。 send(2)
可以在发送少量您要求的内容后返回。
它告诉我,客户端只发送了8个字节并打印出来。
TCP是面向流的协议。您发送字节,它们以相同的顺序到达。因此,当你recv(2)
某事时,你可能会得到更少(或者比你写的更多)。因此,以下情况可能属实:
client:
send 100 bytes
send 400 bytes
server:
recv 50 bytes
recv 150 bytes
recv 250 bytes
recv 50 bytes
使用send
时,recv
和TCP
来电的数量不必相同。
答案 1 :(得分:2)
当您调用send
时,该函数返回实际发送的字节数,此数字可能小于您要发送的字节数。所以每次你想要发送一些东西时,必须有一个像下面这样的循环
bool sendBuffer(SOCKET s, unsigned char *buf, int size)
{
while (size > 0)
{
int sz = send(s, buf, size,0);
if (sz < 0) return false; // Failure
size -= sz; // Decrement number of bytes to send
buf += sz; // Advance read pointer
}
return true; // All buffer has been sent
}
并且在接收时必须执行类似的循环(换句话说,recv
可以返回比您要求的更少的字节。)
如果你不进行这些循环,那么当你在本地机器甚至局域网上工作时,显然的所有东西都会起作用(直到以太网数据包的大小),但是在互联网上工作时,事情不会奏效。
另请注意,正如其他答案所指出的那样,您要求发送sizeof(packet_size)
,即存储该变量所需的字节数,而不是结构的大小。
答案 2 :(得分:1)
有一个非正式的规则,任何人都不得写任何使用TCP的软件,直到他们记住这句话并完全解释它的含义:“TCP是一种不保留应用程序消息边界的字节流协议。” / p>
这意味着TCP只能确保您输入相同的字节并以相同的顺序输出。它不会以任何方式将字节“粘合”在一起。
在编写使用TCP的任何代码之前,您应该使用已经设计的协议(例如IMAP或HTTP)或自己设计一个。如果你自己设计一个,你应该写出一个协议规范。它应该具体定义协议级消息在字节级别将包含的内容。它应该具体说明接收者如何找到消息的结尾,等等。
对于简单的应用程序来说,这看起来有些愚蠢,但相信我,它会大量回报。否则,几乎不可能弄清楚为什么事情不起作用,因为如果服务器和客户端不相处,就没有仲裁者说出什么是正确的。
答案 3 :(得分:0)
我不专注于套接字编程,但我注意到了一些事情。据我所知,我认为你不能轻易地将结构发送到套接字上。您可能希望考虑不同的方法。
注意,当使用send / recv时,你也在确定packet_size的大小,而不是结构的大小。
谷歌搜索提出了通过套接字发送结构:http://ubuntuforums.org/showthread.php?t=613906