我想创建一个可以读取某些数字而不是字符串的套接字,以便我可以对它们执行一些操作。 如何发送整数而不是字符串 这是我目前的计划:
int main(int argc, char *argv[])
{
int sockfd, newsockfd, port, clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2)
error("ERROR, no port provided\n");
port = atoi(argv[1]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port); //host to network
if (bind(sockfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR binding to socket");
listen(sockfd,2);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen);
int n;
void* buffer[256];
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Message received:%d\n",d);
n = write(newsockfd,buffer, strlen((char *)buffer));
if (n < 0)
error("ERROR writing back to socket");
return 0;}
我试过了:
int n= 5;
write(newsockfd,&n, sizeof(int));
但是在客户端(也是一个void *缓冲区),它似乎没有读取任何内容。任何人都可以帮助我如何纠正这个问题?
一种解决方案可能是传递字符串然后转换为int等。但这是正确的方法吗?
答案 0 :(得分:2)
问题是双重的:
第一个问题是声明void* buffer[256]
声明buffer
是一个256个指向void
的数组,而不是我想的那个。相反,如果你想要一个256字节的数组,只需char buffer[256]
。
第二个问题是,在接收方,您将数据视为字符串,但它不是字符串,而是二进制数据值。
第二个问题可以通过两种方式解决:将整数转换为字符串,然后发送该字符串。或者您收到整数的原始数据,并将其转换为int
。第一个解决方案涉及sprintf
,另一个解决方案涉及memcpy
或指针和转换。
对于上面的第一个解决方案,您可以执行以下操作:
char temp[32];
snprintf(temp, sizeof temp, "%d", n);
write(newsockfd, temp, sizeof temp);
在接收端,您将其读作字符串:
char buffer[32];
n = read(newsockfd, buffer, sizeof buffer);
if (n <= 0)
{
// Error or connection closed
}
// TODO: Since TCP is a streaming protocol, we could actually receive
// less than the number of bytes we asked to read, so we need
// to read in a loop
// Print the received data as a string
printf("Received '%s'\n", buffer); // Works because the sender sent with the terminator
// Convert to integer
int i = strtol(buffer, NULL, 10);
printf("Received %d\n", i);
对于上面的第二个解决方案,将整数值作为原始二进制数据发送,但是当收到它时,请执行类似
的操作char buffer[32];
n = read(newsockfd, buffer, sizeof buffer);
if (n <= 0)
{
// Error or connection closed
}
// TODO: Since TCP is a streaming protocol, we could actually receive
// less than the number of bytes we asked to read, so we need
// to read in a loop
int i = *(int *) buffer;
printf("Received %d\n", i);
请注意,此答案中写的第二个解决方案依赖于发件人和收件人具有相同的endianness,以及int
的相同大小(可能不会总是如此)。
最安全的方法通常是在发送端转换为字符串,并将字符串作为字符串接收。即第一个解决方案。
答案 1 :(得分:1)
我想修改提供的清晰回答Joachim Pileborg。
var dbcontext = new ApplicationDbContext(); //foo table is empty
var entry = new Entry { DateTime = DateTime.Now };
dbcontext.Foo.Add();
dbcontext.SaveChanges();
dbcontext.Entry(entry).Reload(); //doesnt suffer from the quirks of dbcontext.Gigs.First()
您知道自己接收了多少字节,因此没有理由阅读更多字节。循环处理他警告的情况:读取(2)可能无法读取所有4个字节(在这种情况下不太可能,但通常不会)。
您始终可以从int value, todo = sizeof(value);
char *p = (void*) &value;
while ( (n = read(newsockfd, p, todo)) < todo ) {
if( n == 0 ) { /* handle eof and break */ }
if( n < 0 ) { /* handle error and break */ }
todo -= n;
p += n
}
if( todo == 0 ) {
printf("Received %d\n", value);
}
获取char *
,并将任何指针传递给接受void *
的函数。你不能做的,便携,是
void *
因为不保证字符数组具有整数对齐。在某些架构上,这会引发SIGBUS。如果您读入字符数组,那么将这些字节解释为整数的安全方法是
char buffer[32];
...
int i = *(int *) buffer;