linux tcp socket并发编程,调用accept函数后调用fork。两台电脑测试,为何accept返回的描述符是相同的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux tcp socket并发编程,调用accept函数后调用fork。两台电脑测试,为何accept返回的描述符是相同的?相关的知识,希望对你有一定的参考价值。

可能是你的fork 之后产生的子进程拷贝的代码,它那里执行了accept,所以导致相同,你试着在每个fork之后的函数中用个exit(1);将子进程退出,然后应该就不会有这个问题了。 参考技术A 返回的描述符是当前可用的最小描述符,你测试环境下的两台电脑可用的最小描述符是一样的。追问

accept返回的描述符不是唯一的么?我连台电脑同时连接,返回的描述符都是4.

追答

这个就比较奇怪了,两个client都能和server正常通信吗?同时。

追问

单独是可以的,但是如果同时开两个必然不好使。。。描述符都一样

追答

那可能就是你程序有问题。

[javaSE] 网络编程(TCP-并发上传图片)

客户端:

1.服务端点

2.读取客户端已有的图片数据

3.通过socket输出流将数据发给服务端

4.读取服务端反馈信息

5.关闭

 

获取Socket对象,new出来,构造参数:String的服务端ipint的端口号

调用Socket对象getOutputStream()方法,得到OutputStream输出流对象

获取FileInputStream对象new出来,构造参数:String的文件路径

while循环调用,条件FileInputStream对象的read()方法,读取到字节数组中

循环中,调用OutputStream输出流对象的write()方法,写入数据,参数:byte[]0len

调用Socket对象的shutDownOutput()方法,通知服务端写入完成

 

调用Socket对象的getInputStream()方法,得到InputStream输入流对象

调用InputStream输入流对象的read()方法,读取,并打印

 

调用FileInputStream对象的close()方法

调用Socket对象的close()方法

 

服务端:

正常读取

 

解决并发

上面的例子,一次只能有一个客户端服务,解决并发上传的问题,使用多线程处理每个来访的客户

定义一个类PicThread,实现Runnable接口

定义构造函数,传递进来Socket对象

实现run()方法,在try-catch中捕获异常,正常读取Socket对象的流

 

 

解决文件覆盖

文件的名称采用ip+(数字),例如:192.168.1.100(2).jpg

获取ip 方法,socket.getInetAddress().getHostAddress()

第一次进入,文件名192.168.1.100.jpg

第二次进入,判读文件已存在,文件名变成192.168.1.100(1).jpg

 

主函数传值形式并判断

判断有一个参数 arg.length==1

判断是文件,并且存在  File对象的exists()方法和isFile()方法

判断文件后缀,File对象的getName().endsWith(“.jpg”)方法

判断文件大小,File对象的length()方法

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

class UploadPicClient {

    /**
     * @param args
     * @throws IOException
     * @throws UnknownHostException
     */
    public static void main(String[] args) throws Exception {
        //判断参数
        if(args.length!=1){
            System.out.println("请选择一个文件");
            return;
        }
        File file=new File(args[0]);
        if(!file.exists()||!file.isFile()){
            System.out.println("请选择一个存在的文件");
            return;
        }
        if(!file.getName().endsWith(".png")||file.length()>(1024*1024)){
            System.out.println("请选择小于1M的png文件");
            return;
        }
        Socket socket = new Socket("127.0.0.1", 10001);
        OutputStream out = socket.getOutputStream();
        // 输出
        FileInputStream fileInputStream = new FileInputStream("E:/11.png");
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = fileInputStream.read(b)) != -1) {
            out.write(b, 0, len);
        }
        // 通知服务端
        socket.shutdownOutput();

        // 接收反馈
        InputStream inputStream = socket.getInputStream();
        byte[] res = new byte[1024];
        len = inputStream.read(res);
        System.out.println(new String(res, 0, len));

        out.close();
        socket.close();
    }

}
/**
 * 多线程上传
 * @author taoshihan
 *
 */
class UploadPicServerThread implements Runnable {
    private Socket socket;

    public UploadPicServerThread(Socket s) {
        this.socket = s;
    }

    @Override
    public void run() {
        // 读取
        InputStream is;
        try {
            is = socket.getInputStream();

            byte[] res = new byte[1024];
            int len = 0;
            // 解决文件覆盖
            String ip = socket.getInetAddress().getHostAddress();
            int fileNum = 1;
            File file = new File(ip + ".png");
            while (file.exists()) {
                file = new File(ip + "(" + (fileNum++) + ").png");
            }
            FileOutputStream fos = new FileOutputStream(file);
            while ((len = is.read(res)) != -1) {
                fos.write(res, 0, len);
            }

            // 反馈
            OutputStream os = socket.getOutputStream();
            os.write("上传成功!".getBytes());
            is.close();
            os.close();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

// 服务端
public class UploadPicServer {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(10001);

        while (true) {
            Socket socket = serverSocket.accept();
            new Thread(new UploadPicServerThread(socket)).start();
        }
    }

}

以上是关于linux tcp socket并发编程,调用accept函数后调用fork。两台电脑测试,为何accept返回的描述符是相同的?的主要内容,如果未能解决你的问题,请参考以下文章

Linux下高并发网络编程

[javaSE] 网络编程(TCP-并发上传图片)

五十linux 编程——TCP 编程模型

Linux网络编程基础及多线程并发案例

Linux网络学习_TCP客户端服务器编程

TCP/IP Socket网络编程