Unix 通过TCP套接字发送char缓冲区不完整
我正在学习如何在C中处理套接字和TCP连接。我有一个应用程序(一个很长的应用程序),它基本上通过系统调用从服务器到客户端发送和接收字符数组,反之亦然(当然是两个独立的C应用程序)。只要我在同一台PC上通过本地连接使用它,在一台终端上运行服务器,在另一台终端上运行客户机,一切正常,数据就会到达目的地。但是,如果我在一台计算机上使用服务器,在另一台计算机上使用客户端,但在同一条internet线路上,向客户端传递一个类似192.168.1.X的地址(取自服务器运行的机器),在建立连接后,我会得到一个错误,告诉我预期的字节数(在发送真正的字符[]之前我通过了它)没有到达。如果我在我的电脑上尝试服务器,在另一台电脑上尝试客户端,在另一个提供商上尝试不同的线路,也是一样的 我遗漏了一些东西,按顺序发送一堆字节有什么限制吗 出现错误的代码 服务器端:Unix 通过TCP套接字发送char缓冲区不完整,unix,tcp,sockets,c,Unix,Tcp,Sockets,C,我正在学习如何在C中处理套接字和TCP连接。我有一个应用程序(一个很长的应用程序),它基本上通过系统调用从服务器到客户端发送和接收字符数组,反之亦然(当然是两个独立的C应用程序)。只要我在同一台PC上通过本地连接使用它,在一台终端上运行服务器,在另一台终端上运行客户机,一切正常,数据就会到达目的地。但是,如果我在一台计算机上使用服务器,在另一台计算机上使用客户端,但在同一条internet线路上,向客户端传递一个类似192.168.1.X的地址(取自服务器运行的机器),在建立连接后,我会得到一个
r=htonl(lghstr);
w=write(myFd,&r,sizeof(int));//writes the number of incoming bytes
if(w<0) perror("writeServer4"),exit(-1);
w=write(myFd,tmp->string,lghstr);
if(w<0) perror("writeServer5"),exit(-1);
if(w!=lghstr) perror("ERROR");
r=htonl(lghstr);
w=write(myFd,&r,sizeof(int));//写入传入字节数
if(wstring,lghstr);
如果(w你在一边做了ntohl()
,而不是在另一边。这可能是用错误的值解释字节
您应该printf()
两侧的字节,并查看int的计算结果
编辑:我确信这是一个记录在案的编程错误
如果让我猜的话,我会说由于某种原因,你和另一方不同步。你说这运行“大约300次”
尝试向协议中添加一个神奇的整数
下面是一个按此顺序发送的客户机示例
一个始终不变的神奇整数
将要发送的字节长度
要发送的字节数
这使用了分散-聚集机制(它更适合序列化),但除此之外,它有效地做了与客户机相同的事情,只是增加了一个神奇的价值
当接收器接收到数据时,它可以通过检查输入的幻数来验证数据的顺序是否正确。如果幻数错误,则表示客户端或服务器在流中的位置丢失了自己
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <err.h>
#include <time.h>
#define MAGIC 0xDEADBEEFLU
#define GARBAGE_MAX 65536
const int iterations = 3000;
char * create_garbage_buf(
void)
{
int rc = -1;
int fd = -1;
char *buf = NULL;
buf = malloc(GARBAGE_MAX);
if (!buf)
err(1, "Cannot allocate buf");
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
err(1, "Cannot open urandom");
rc = read(fd, buf, GARBAGE_MAX);
if (rc < 0)
err(1, "Cannot read from urandom");
else if (rc != GARBAGE_MAX)
errx(1, "Expected %d bytes, but got %d reading from urandom",
GARBAGE_MAX, rc);
close(fd);
return buf;
}
int main() {
int fd, offset, i, rc;
uint32_t magic = MAGIC;
uint32_t blen = 0;
char *buf = NULL;
struct iovec vecs[3];
/* Seed poor random number generator */
srand(time(NULL));
/* Use a file for demonstration, but a socket will do just fine */
fd = open("/dev/null", O_WRONLY);
/* Create some garbage to send */
buf = create_garbage_buf();
if (fd < 0)
err(1, "Cannot open file");
/* The first vector, is always the magic */
vecs[0].iov_len = sizeof(uint32_t);
vecs[0].iov_base = &magic;
for (i=0; i < iterations; i++) {
/* The second vector represents lengh of what we send
* in this demonstration it is a number between 0 and
* GARBAGE_MAX/2.
*/
blen = rand() % (GARBAGE_MAX / 2);
vecs[1].iov_len = sizeof(uint32_t);
vecs[1].iov_base = &blen;
/* The last record is the data to send. Its another random
* number between 0 and GARBAGE_MAX which represents the offset
* in our garbage data to send */
offset = rand() % (GARBAGE_MAX / 2);
vecs[2].iov_len = blen;
vecs[2].iov_base = &buf[offset];
rc = writev(fd, vecs, 3);
if (rc < 0)
err(1, "Could not write data");
if (rc != (sizeof(uint32_t)*2 + blen))
errx(1, "Did not write proper number of bytes to handle");
printf("Wrote %u bytes from offset %u in garbage\n", blen, offset);
}
free(buf);
printf("Done!\n");
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义致命流感的魔力
#定义垃圾量(最大值65536)
常数int迭代次数=3000;
char*创建垃圾(
(无效)
{
int rc=-1;
int-fd=-1;
char*buf=NULL;
buf=malloc(最大垃圾量);
如果(!buf)
错误(1,“无法分配buf”);
fd=开放(“/dev/uradom”,仅限O_rdon);
如果(fd<0)
错误(1,“无法打开urandom”);
rc=读取(fd、buf、垃圾_最大值);
if(rc<0)
错误(1,“无法从Uradom读取”);
else if(rc!=垃圾_MAX)
errx(1,“预期有%d个字节,但从Uradom读取了%d个”,
垃圾(最大值,rc);
关闭(fd);
返回buf;
}
int main(){
int-fd,偏移量,i,rc;
uint32_t magic=魔法;
uint32_t blen=0;
char*buf=NULL;
结构iovec-vecs[3];
/*种子贫乏随机数发生器*/
srand(时间(空));
/*使用一个文件进行演示,但是一个套接字就可以了*/
fd=打开(“/dev/null”,仅限O_wr);
/*创建一些要发送的垃圾*/
buf=创建_垃圾_buf();
如果(fd<0)
错误(1,“无法打开文件”);
/*第一个向量,永远是魔法*/
向量[0].iov_len=sizeof(uint32_t);
向量[0]。iov_base=&magic;
对于(i=0;i
您只在一侧执行ntohl()
。这可能是用错误的值解释字节
您应该printf()
两侧的字节,并查看int的计算结果
编辑:我确信这是一个记录在案的编程错误
如果让我猜的话,我会说由于某种原因,你和另一方不同步。你说这运行“大约300次”
尝试向协议中添加一个神奇的整数
下面是一个按此顺序发送的客户机示例
一个始终不变的神奇整数
将要发送的字节长度
要发送的字节数
这使用了分散-聚集机制(它更适合序列化),但除此之外,它有效地做了与客户机相同的事情,只是增加了一个神奇的价值
当接收器接收到数据时,它可以通过检查输入的幻数来验证数据的顺序是否正确。如果幻数错误,则表示客户端或服务器在流中的位置丢失了自己
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <err.h>
#include <time.h>
#define MAGIC 0xDEADBEEFLU
#define GARBAGE_MAX 65536
const int iterations = 3000;
char * create_garbage_buf(
void)
{
int rc = -1;
int fd = -1;
char *buf = NULL;
buf = malloc(GARBAGE_MAX);
if (!buf)
err(1, "Cannot allocate buf");
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
err(1, "Cannot open urandom");
rc = read(fd, buf, GARBAGE_MAX);
if (rc < 0)
err(1, "Cannot read from urandom");
else if (rc != GARBAGE_MAX)
errx(1, "Expected %d bytes, but got %d reading from urandom",
GARBAGE_MAX, rc);
close(fd);
return buf;
}
int main() {
int fd, offset, i, rc;
uint32_t magic = MAGIC;
uint32_t blen = 0;
char *buf = NULL;
struct iovec vecs[3];
/* Seed poor random number generator */
srand(time(NULL));
/* Use a file for demonstration, but a socket will do just fine */
fd = open("/dev/null", O_WRONLY);
/* Create some garbage to send */
buf = create_garbage_buf();
if (fd < 0)
err(1, "Cannot open file");
/* The first vector, is always the magic */
vecs[0].iov_len = sizeof(uint32_t);
vecs[0].iov_base = &magic;
for (i=0; i < iterations; i++) {
/* The second vector represents lengh of what we send
* in this demonstration it is a number between 0 and
* GARBAGE_MAX/2.
*/
blen = rand() % (GARBAGE_MAX / 2);
vecs[1].iov_len = sizeof(uint32_t);
vecs[1].iov_base = &blen;
/* The last record is the data to send. Its another random
* number between 0 and GARBAGE_MAX which represents the offset
* in our garbage data to send */
offset = rand() % (GARBAGE_MAX / 2);
vecs[2].iov_len = blen;
vecs[2].iov_base = &buf[offset];
rc = writev(fd, vecs, 3);
if (rc < 0)
err(1, "Could not write data");
if (rc != (sizeof(uint32_t)*2 + blen))
errx(1, "Did not write proper number of bytes to handle");
printf("Wrote %u bytes from offset %u in garbage\n", blen, offset);
}
free(buf);
printf("Done!\n");
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义致命流感的魔力
#定义垃圾量(最大值65536)
常数int迭代次数=3000;
char*创建垃圾(
(无效)
{
int rc=-1;
int-fd=-1;
char*buf=NULL;
buf=malloc(最大垃圾量);
如果(!buf)
错误(1,“无法分配buf”);
fd=开放(“/dev/uradom”,仅限O_rdon);
rC=read(fdc,dest,lghstr);
...
if(rC!=lghstr) perror("error : ")
size_t count = 0;
while (count < lghstr)
{
ssize_t readresult = read(fdc, dest+count, lghstr-count);
if (readresult == -1)
{
// socket error - handle appropriately (typically, just close the connection)
}
else if (readresult == 0)
{
// The other side closed the connection - handle appropriately (close the connection)
}
else
{
count += readresult;
}
}
rc = recv(fdc, dest, lghstr, MSG_WAITALL);
if (rc == -1)
{
// socket error
}
else if (rc == 0)
{
// socket closed by remote
}
else if (rc < lghstr)
{
// the other side likely closed the connection and this is residual data (next recv will return 0)
}