问一个关于socket的问题

这个冬天有点冷灬 2017-07-01 04:59:33
http://bbs.csdn.net/topics/392186524
这是我上次遇到的问题,后来发现一部分原因,但是还是很疑惑,希望大家可以帮助我解决疑惑。
上次的问题后来我发现原因是,客户端一连上来有发送数据,而我没有去read客户端发送的数据,然后去调用两次write之后去close(fd)导致服务端只会发送第一次调用write的的数据,然后我把close(fd)去掉发现是可以将两次write的数据都发送出去,或者先将客户端发来的数据都读取完(必须读取完,读取一半也不行)然后close掉也是可以的。但是这两者都有弊端啊,第一个你不close(fd)或导致随着连接次数的增加,fd会持续增长,然后会被吃光。第二种,如果你读到一半,发现客户端发来的数据有问题,不想读了直接返回数据给客户端这种就做不到了啊。一开始我以为是epoll的问题,后来我直接用最直接的方式去做测试也不行。难道不读客户端发来的数据会影响写操作吗?下面是我写的测试代码:
服务端是用Linux c写的
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

int main(void) {
struct sockaddr_in server_addr;
int err = 0;
int ss = socket(AF_INET, SOCK_STREAM, 0);
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
server_addr.sin_port = htons(8080);
err = bind(ss, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(err < 0) {
printf("bind error\n");
return -1;
}
listen(ss, 10);
if(err < 0) {
printf("bind error\n");
return -1;
}
socklen_t addrlen;
while(1) {
int fd = accept(ss, (struct sockaddr*)&addrlen, &addrlen);
//char buffer[1024];
//read(s, buffer, 1024); 这个地方先注释掉就会发现第二次的write写不出去
int len = write(fd, "hello", 5);
int len2 = write(fd, "world", 5);
printf("fd:%d\n", fd);
printf("len:%d\n", len);
printf("len2:%d\n", len2);
printf("===========================\n");
close(fd);//把这句注释就能将第二次write的数据写出去
}

return 0;
}


客户端测试代码用的是java
package com.example.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class SocketTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++){
socketTest();
}
}

public static void socketTest() {
Socket socket = null;
try {
socket = new Socket("192.168.1.151", 8080);
InputStream is = socket.getInputStream();
byte[] buffer = new byte[128];
OutputStream os = socket.getOutputStream();
os.write("hello world".getBytes());
int len = is.read(buffer, 0, 5);
is.read(buffer, len, 5);
System.out.println("len:" + len);
System.out.println(new String(buffer));
} catch (IOException e) {
e.printStackTrace();
} finally {
if(socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

大家帮忙看看啊 ,谢谢了!
...全文
315 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhujinqiang 2017-07-03
  • 打赏
  • 举报
回复
接收的数据先放在缓存buffer里面 处理逻辑是从buffer分析处理,检测字符串的结束字符,一般是‘\0’作为字符串的结束
赵4老师 2017-07-03
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://bbs.csdn.net/topics/380167545
Van_Le 2017-07-02
  • 打赏
  • 举报
回复
引用 2 楼 kang2618 的回复:
引用 1楼RLib 的回复:
客户端write完你服务端这边就close了, 导致客户端java read中断
那这种情况应该怎么解决呢?


测试配置:linux c ,windows VC
测试结果:
结论:客户端的接受缓存在读取字符串时,记住需要有‘\0’作为字符串的结尾,否则读不出来,除非幸运的遇上一个'\0'.
实践解释:
补充:若没问题请结帖,有问题欢迎讨论!谢谢!
  • 打赏
  • 举报
回复
引用 1楼RLib 的回复:
客户端write完你服务端这边就close了, 导致客户端java read中断
那这种情况应该怎么解决呢?
RLib 2017-07-01
  • 打赏
  • 举报
回复
客户端write完你服务端这边就close了, 导致客户端java read中断

69,371

社区成员

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

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