外网做socket通信--问题

cook_fish 2014-08-21 04:13:37
各位高手,我在外网做一个socket通信程序,现在遇到这样的问题,请教一下:
client端发送一个文件数据的时候,小一点的没问题,大一点的比如8k,server端读了2-3个1024字节之后就会阻塞,client端发送了10个左右的1024字节之后也会阻塞,有高手指点一下吗?
程序在局域网内测试都是没问题的。但是一放到外网来,就这样。
程序还有一些没贴出来的,都是变量的定义。
client:

memset(&ser_addr, 0, sizeof(ser_addr));
memset(&host_addr, 0, sizeof(host_addr));
ser_addr.sin_family = AF_INET;
inet_aton(REMOTE_IP, (struct in_addr *)&ser_addr.sin_addr);
ser_addr.sin_port = htons(SERVER_PORT);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
printf("%s, %d, create socket failed\n", __FILE__, __LINE__);
exit(1);
}

setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&brecord_flag, sizeof(brecord_flag));
setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&brecord_flag, sizeof(brecord_flag));

bind(sock_fd, (struct sockaddr *)&host_addr, sizeof(host_addr));

if (connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)
{
printf("%s, %d, connect socket failed\n", __FILE__, __LINE__);
exit(1);
}

if ((from_fd = open(argv[1], O_RDONLY)) == -1)
{
fprintf(stderr, "Open %s Error: %s\n", argv[1], strerror(errno));
exit(1);
}

filesize = get_file_size(argv[1]);
if (filesize <= 0)
exit(1);

left_size = filesize;
while(left_size > 0)
{
bytes_read = read(from_fd, buffer, BUFFER_SIZE);
if (bytes_read <= 0)
{
printf("read end!\n");
close(from_fd);
break;
}

sendlen = bytes_read;
retlen = send(sock_fd, buffer, sendlen, 0);
printf("retlen = %d\n", retlen);
if (retlen < 0)
{
if (errno == EINTR)
{
retlen = 0;
printf("continue wait for send!\n");

}
else
{
printf("error to send %s\n", strerror(errno));
printf("recreate sock\n");
close(sock_fd);
close(from_fd);
goto L1;
}
}

left_size -= retlen;
}

return 0;


server:

void *rcvData(void *arg)
{
int cnfd = *((int *)arg);
char recvbuf[RECV_BUF_SIZE] = {0};
int bytes_write;
int retlen = 0;
char fileName[MAX_FILE_NAME_LEN];
int to_fd;
char BindFileName[MAX_FILE_NAME_LEN];


sprintf(fileName, "store_file_%d.ts", pthread_count);
strcpy(BindFileName, fileName);
// if ((to_fd = open(fileName, O_RDWR | O_CREAT, 0777)) == -1)
// {
// printf("Open %s Error: %s\n", fileName, strerror(errno));
// exit(1);
// }

#if 0
if(fcntl(cnfd, F_SETFL, O_NONBLOCK) == -1) {
printf("error to set NONBLOCK!\n");
exit(1);
}
#endif


while (1)
{
pthread_mutex_lock(&mutex);
//pthread_cond_wait(&cond, &mutex);

printf("recv onece __line %d\n", __LINE__);
memset(recvbuf, 0, sizeof(recvbuf));
//retlen = recv(cnfd, recvbuf, RECV_BUF_SIZE, 0);
retlen = recv(cnfd, recvbuf, RECV_BUF_SIZE, MSG_NOSIGNAL);
printf("retlen = %d\n", retlen);
if(retlen < 0)
{
if (errno == EINTR || errno == EAGAIN)
{
pthread_mutex_unlock(&mutex);
continue;
}

printf("recv Error: %s\n", strerror(errno));
break;
}
else if (retlen == 0)
{
printf("recv end!\n");
pthread_mutex_unlock(&mutex);
break;
}

printf("recv onece __line %d\n", __LINE__);

if ((to_fd = open(BindFileName, O_RDWR | O_CREAT | O_APPEND, 0777)) == -1)
{
printf("Open %s Error: %s\n", fileName, strerror(errno));
exit(1);
}

bytes_write = write(to_fd, recvbuf, retlen);
if (bytes_write != retlen)
{
printf("write file error!\n");
break;
}

printf("recv onece __line %d\n", __LINE__);

close(to_fd);
pthread_mutex_unlock(&mutex);
}


pthread_mutex_unlock(&mutex);
close(cnfd);
pthread_exit(NULL);
}

int main
{
...
pthread_mutex_init(&mutex, NULL);
//pthread_cond_init(&cond, NULL);

memset((void *)&hostaddr, 0, sizeof(hostaddr));
memset((void *)&clientaddr, 0, sizeof(clientaddr));
hostaddr.sin_family = AF_INET;
hostaddr.sin_port = htons(LISTEN_PORT);
hostaddr.sin_addr.s_addr = htonl(INADDR_ANY);

listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sock < 0)
{
printf("%s, %d, create socket failed\n", __FILE__, __LINE__);
exit(1);
}

if(bind(listen_sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr)) < 0)
{
printf("%s, %d, bind socket failed\n", __FILE__, __LINE__);
exit(1);
}

//if(listen(listen_sock, MAX_LISTEN_NUM) < 0)
if(listen(listen_sock, SOMAXCONN) < 0)//128
{
printf("%s, %d, listen failed\n", __FILE__, __LINE__);
exit(1);
}

while(1)
{
app_sock = accept(listen_sock, (struct sockaddr *)&clientaddr, &socklen);
if(app_sock < 0)
{
printf("%s:%d, accept failed", __FILE__, __LINE__);
exit(1);
}
else
{
printf("There is a new socket link coming %d!\n", app_sock);
if (pthread_create(&tid, NULL, rcvData, &app_sock))
{
perror("rcv pthread_create\n");
}

pthread_count += 1;

}
}

}

...全文
271 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
cook_fish 2014-08-23
  • 打赏
  • 举报
回复
谢谢各位解答。 问题已经解决。 程序本身没有什么太大问题。 是公司路由这边设置有问题,导致数据包只能收到几个。
cook_fish 2014-08-22
  • 打赏
  • 举报
回复
引用 5 楼 cheng7068 的回复:
看了一下你的代码,不知道你的锁用在这里的作用是什么;另外在线程传递参数的时候最好用结构体指针传递参数,你直接用SOCKET类型的引用,这个很容易早晨问题的,不明白你的调试环境,就这么多了
谢谢。 锁和线程的话,我都去掉了。测试起来,还是一样有问题。 环境的话我说的详细点吧,不好意思。 客户端和服务器端,处于2个不同的网络中。 比如客户端是你家里的网络,服务器是你公司的网络。 从客户端发起请求连接到服务器,建立连接之后,2者进行数据传递。 这就是我说的外网。 我说的局域网测试通过,就是 客户端和服务器都在你公司的网络里,直接用192.168.2.xxx的网络就可以传递了,这样测试是没问题的。
风行踩火轮 2014-08-22
  • 打赏
  • 举报
回复
看了一下你的代码,不知道你的锁用在这里的作用是什么;另外在线程传递参数的时候最好用结构体指针传递参数,你直接用SOCKET类型的引用,这个很容易早晨问题的,不明白你的调试环境,就这么多了
cook_fish 2014-08-22
  • 打赏
  • 举报
回复
引用 3 楼 angel_su 的回复:
貌似lock/unlock的点不对,譬如外网可能有来源不明的连接,对应线程拿到锁后recv不到阻塞了,其他正常连接的线程拿不到锁也不跑了...
我试过把lock去掉,还是同样的会出现问题。 谢谢你呀,都没人鸟我。。 tcp协议应该就可以直接传送了吧?不需要再外加别的头了吧(比如HTTP)?
angel_su 2014-08-22
  • 打赏
  • 举报
回复
貌似lock/unlock的点不对,譬如外网可能有来源不明的连接,对应线程拿到锁后recv不到阻塞了,其他正常连接的线程拿不到锁也不跑了...
cook_fish 2014-08-22
  • 打赏
  • 举报
回复
更新一下问题,经过测试,我把client端发送速度调慢,1s发送一个字符串到server, server这边第一次会及时接收到,但是server端第2次接收时候就处于阻塞态了。这时让程序继续进行那么1分来钟,再直接把client端断开,ctrl+c。发现server端一次性把前面的数据都收到了。但是如果时间久了就不行,时间久了,我想应该是server端认为这个socket已经是断开的,所以不去收数据了。现在这样,我该怎么去处理,让server立即接收数据,不处于等待状态呢?
cook_fish 2014-08-21
  • 打赏
  • 举报
回复
高手快点出现啊。急急急!

69,335

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧